Skip to content

Commit 234aef7

Browse files
authored
XSA-474 fix: Simplify UTF-8 decoding (#6659)
* Use the decoder from the OCaml standard library instead of our own implementation, which this patch removes. * Validate UTF-8/XML conformance for maps and sets, in addition to strings. This is XSA-474 / CVE-2025-58146. Reviewed-by: Edwin Török <edwin.torok@cloud.com> Patch from: https://xenbits.xen.org/xsa/advisory-474.html
2 parents 89d78a5 + 6aa075a commit 234aef7

File tree

12 files changed

+139
-816
lines changed

12 files changed

+139
-816
lines changed

ocaml/database/db_cache_impl.ml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ let read_field t tblname fldname objref =
6767
occurs. *)
6868
let ensure_utf8_xml string =
6969
let length = String.length string in
70-
let prefix =
71-
Xapi_stdext_encodings.Encodings.UTF8_XML.longest_valid_prefix string
72-
in
70+
let prefix = Xapi_stdext_encodings.Utf8.XML.longest_valid_prefix string in
7371
if length > String.length prefix then
7472
warn "string truncated to: '%s'." prefix ;
7573
prefix
@@ -86,20 +84,32 @@ let write_field_locked t tblname objref fldname newval =
8684
(get_database t)
8785
)
8886

87+
(** Ensure a value is conforming to UTF-8 with XML restrictions *)
88+
let is_valid v =
89+
let valid = Xapi_stdext_encodings.Utf8.XML.is_valid in
90+
let valid_pair (x, y) = valid x && valid y in
91+
match v with
92+
| Schema.Value.String s ->
93+
valid s
94+
| Schema.Value.Set ss ->
95+
List.for_all valid ss
96+
| Schema.Value.Pairs pairs ->
97+
List.for_all valid_pair pairs
98+
99+
let share_string = function
100+
| Schema.Value.String s ->
101+
Schema.Value.String (Share.merge s)
102+
| v ->
103+
(* we assume strings in the tree have been shared already *)
104+
v
105+
89106
let write_field t tblname objref fldname newval =
90-
let newval =
91-
match newval with
92-
| Schema.Value.String s ->
93-
(* the other caller of write_field_locked only uses sets and maps,
94-
so we only need to check for String here
95-
*)
96-
if not (Xapi_stdext_encodings.Encodings.UTF8_XML.is_valid s) then
97-
raise Invalid_value ;
98-
Schema.Value.String (Share.merge s)
99-
| _ ->
100-
newval
101-
in
102-
with_lock (fun () -> write_field_locked t tblname objref fldname newval)
107+
if not @@ is_valid newval then
108+
raise Invalid_value
109+
else
110+
with_lock (fun () ->
111+
write_field_locked t tblname objref fldname (share_string newval)
112+
)
103113

104114
let touch_row t tblname objref =
105115
update_database t (touch tblname objref) ;

ocaml/database/string_marshall_helper.ml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ module D = Debug.Make (struct let name = __MODULE__ end)
2222

2323
let ensure_utf8_xml string =
2424
let length = String.length string in
25-
let prefix =
26-
Xapi_stdext_encodings.Encodings.UTF8_XML.longest_valid_prefix string
27-
in
25+
let prefix = Xapi_stdext_encodings.Utf8.XML.longest_valid_prefix string in
2826
if length > String.length prefix then
2927
D.warn "Whilst doing 'set' of structured field, string truncated to: '%s'."
3028
prefix ;

ocaml/idl/ocaml_backend/gen_server.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ let gen_module api : O.Module.t =
457457
([
458458
"let __call, __params = call.Rpc.name, call.Rpc.params in"
459459
; "List.iter (fun p -> let s = Rpc.to_string p in if not \
460-
(Xapi_stdext_encodings.Encodings.UTF8_XML.is_valid s) then"
460+
(Xapi_stdext_encodings.Utf8.is_valid s) then"
461461
; "raise (Api_errors.Server_error(Api_errors.invalid_value, \
462462
[\"Invalid UTF-8 string in parameter\"; s]))) __params;"
463463
; "let __label = __call in"

ocaml/libs/xapi-stdext/lib/xapi-stdext-encodings/bench/bench_encodings.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
open Bechamel
2-
open Xapi_stdext_encodings.Encodings
2+
open Xapi_stdext_encodings
33

44
let test name f =
55
Test.make_indexed_with_resource ~name ~args:[10; 1000; 10000]
@@ -10,6 +10,6 @@ let test name f =
1010

1111
let benchmarks =
1212
Test.make_grouped ~name:"Encodings.validate"
13-
[test "UTF8_XML" UTF8_XML.validate]
13+
[test "UTF8.XML" Utf8.XML.is_valid]
1414

1515
let () = Bechamel_simple_cli.cli benchmarks
Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
(library
22
(name xapi_stdext_encodings)
33
(public_name xapi-stdext-encodings)
4-
(modules :standard \ test)
4+
(modules :standard)
55
)
66

7-
(test
8-
(name test)
9-
(package xapi-stdext-encodings)
10-
(modules test)
11-
(libraries alcotest xapi-stdext-encodings)
12-
)

ocaml/libs/xapi-stdext/lib/xapi-stdext-encodings/encodings.ml

Lines changed: 0 additions & 167 deletions
This file was deleted.

ocaml/libs/xapi-stdext/lib/xapi-stdext-encodings/encodings.mli

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)