Skip to content

Commit e983348

Browse files
committed
compare: conform to canonical DNS name order
1 parent 84d5bd6 commit e983348

File tree

4 files changed

+42
-13
lines changed

4 files changed

+42
-13
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v0.4.0 (2022-01-07)
2+
3+
* compare: conform to canonical DNS name order (RFC 4034, Section 6.1)
4+
15
## v0.3.1 (2021-10-27)
26

37
* remove fmt and astring dependency

domain_name.ml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,18 +198,17 @@ let compare_label a b =
198198
String.compare (String.lowercase_ascii a) (String.lowercase_ascii b)
199199

200200
let compare_domain cmp_sub a b =
201-
let la = Array.length a in
202-
match compare la (Array.length b) with
203-
| 0 ->
204-
let rec cmp idx =
205-
if idx = la then 0
206-
else
207-
match cmp_sub (Array.get a idx) (Array.get b idx) with
208-
| 0 -> cmp (succ idx)
209-
| x -> x
210-
in
211-
cmp 0
212-
| x -> x
201+
let al = Array.length a and bl = Array.length b in
202+
let rec cmp idx =
203+
if al = bl && al = idx then 0
204+
else if al = idx then -1
205+
else if bl = idx then 1
206+
else
207+
match cmp_sub (Array.get a idx) (Array.get b idx) with
208+
| 0 -> cmp (succ idx)
209+
| x -> x
210+
in
211+
cmp 0
213212

214213
let compare = compare_domain compare_label
215214

domain_name.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ val equal : ?case_sensitive:bool -> 'a t -> 'b t -> bool
165165

166166
val compare : 'a t -> 'b t -> int
167167
(** [compare t t'] compares the domain names [t] and [t'] using a case
168-
insensitive string comparison. *)
168+
insensitive string comparison. This conforms to the canonical DNS name
169+
order, as described in RFC 4034, Section 6.1. *)
169170

170171
val equal_label : ?case_sensitive:bool -> string -> string -> bool
171172
(** [equal_label ~case_sensitive a b] is [true] if [a] and [b] are equal

tests.ml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
let n_of_s = Domain_name.of_string_exn
22

3+
let raw =
4+
let module M = struct
5+
type t = [ `raw ] Domain_name.t
6+
let pp = Domain_name.pp
7+
let equal = Domain_name.equal ~case_sensitive:false
8+
end in (module M: Alcotest.TESTABLE with type t = M.t)
9+
310
let host =
411
let module M = struct
512
type t = [ `host ] Domain_name.t
@@ -247,6 +254,23 @@ let get_and_count_and_find_label () =
247254
Alcotest.(check (option int) "find_label ~back:true www.www.www 'www' is 2"
248255
(Some 2) Domain_name.(find_label ~rev:true n' (equal_label "www")))
249256

257+
let test_compare_canonical () =
258+
(* from RFC 4034, 6.1 *)
259+
let names = List.map n_of_s [
260+
"example" ;
261+
"a.example" ;
262+
"yljkjljk.a.example" ;
263+
"Z.a.example" ;
264+
"zABC.a.EXAMPLE" ;
265+
"z.example" ;
266+
"\001.z.example" ;
267+
"*.z.example" ;
268+
"\200.z.example"
269+
] in
270+
let sorted_names = List.sort Domain_name.compare names in
271+
Alcotest.(check (list raw) "compare fulfills canonical form and order"
272+
names sorted_names)
273+
250274
let tests = [
251275
"basic predicates", `Quick, basic_preds ;
252276
"basic name stuff", `Quick, basic_name ;
@@ -255,6 +279,7 @@ let tests = [
255279
"fqdn around", `Quick, fqdn_around ;
256280
"drop labels", `Quick, drop_labels ;
257281
"get and count and find labels", `Quick, get_and_count_and_find_label ;
282+
"sorting", `Quick, test_compare_canonical ;
258283
]
259284

260285
let suites = [

0 commit comments

Comments
 (0)