Repository: netbox-community/netbox

Issue:
Add bulk interface validation missing causes server error
### NetBox version

v3.5.1

### Python version

3.8

### Steps to Reproduce

1 click in add interface on any device
2 try to create severals interfaces in bulk mode for example Gi[11-8] (of course wrong interface order should not cause application error)
![add a new interface v3 5 1 bug](https://github.com/netbox-community/netbox/assets/57568271/ee4e1895-09d5-4bb9-a0c1-c11760e14ef3)
![github 3 5 1 interface bug](https://github.com/netbox-community/netbox/assets/57568271/cef37695-21ef-450a-ae29-6bc6e4e37f49)

3 click save button

### Expected Behavior

a warning message would be spected to correct wrong interface order

### Observed Behavior

Server Error
contact server admin message raised.
![github 3 5 1 interface bug](https://github.com/netbox-community/netbox/assets/57568271/b9b549f1-6ad3-4ac2-9bb4-7997f608aefb)



Discussion:
I would like to take ownership of this issue. 
@dhenschen do you still want to take ownership of this?
@arthanson You can move this back to unassigned. Thanks!

Resolving patch:
diff --git a/netbox/dcim/forms/object_create.py b/netbox/dcim/forms/object_create.py
--- a/netbox/dcim/forms/object_create.py
+++ b/netbox/dcim/forms/object_create.py
@@ -52,7 +52,10 @@ def clean(self):
         super().clean()
 
         # Validate that all replication fields generate an equal number of values
-        pattern_count = len(self.cleaned_data[self.replication_fields[0]])
+        if not (patterns := self.cleaned_data.get(self.replication_fields[0])):
+            return
+
+        pattern_count = len(patterns)
         for field_name in self.replication_fields:
             value_count = len(self.cleaned_data[field_name])
             if self.cleaned_data[field_name] and value_count != pattern_count:
diff --git a/netbox/utilities/forms/utils.py b/netbox/utilities/forms/utils.py
--- a/netbox/utilities/forms/utils.py
+++ b/netbox/utilities/forms/utils.py
@@ -60,6 +60,9 @@ def parse_alphanumeric_range(string):
         except ValueError:
             begin, end = dash_range, dash_range
         if begin.isdigit() and end.isdigit():
+            if int(begin) >= int(end):
+                raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
+
             for n in list(range(int(begin), int(end) + 1)):
                 values.append(n)
         else:
@@ -71,6 +74,10 @@ def parse_alphanumeric_range(string):
                 # Not a valid range (more than a single character)
                 if not len(begin) == len(end) == 1:
                     raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
+
+                if ord(begin) >= ord(end):
+                    raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
+
                 for n in list(range(ord(begin), ord(end) + 1)):
                     values.append(chr(n))
     return values


Test patch:
diff --git a/netbox/utilities/tests/test_forms.py b/netbox/utilities/tests/test_forms.py
--- a/netbox/utilities/tests/test_forms.py
+++ b/netbox/utilities/tests/test_forms.py
@@ -264,8 +264,9 @@ def test_invalid_range_alphanumeric(self):
         self.assertEqual(sorted(expand_alphanumeric_pattern('r[a-9]a')), [])
 
     def test_invalid_range_bounds(self):
-        self.assertEqual(sorted(expand_alphanumeric_pattern('r[9-8]a')), [])
-        self.assertEqual(sorted(expand_alphanumeric_pattern('r[b-a]a')), [])
+        with self.assertRaises(forms.ValidationError):
+            sorted(expand_alphanumeric_pattern('r[9-8]a'))
+            sorted(expand_alphanumeric_pattern('r[b-a]a'))
 
     def test_invalid_range_len(self):
         with self.assertRaises(forms.ValidationError):