My own corner of monopam
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix implicit scalar conversion to numbers #1

open opened by anil.recoil.org targeting main

classify_scalar runs implicit type resolution (int → float → bool/null → string) on every YAML scalar, regardless of whether the scalar was plain or quoted in the source. This is incorrect per the YAML 1.2.2 spec.

YAML 1.2.2 §10.3.2 (Tag Resolution) states that single- and double-quoted scalars resolve to tag:yaml.org,2002:str and must not go through implicit content-based type resolution. Only plain (unquoted) scalars are resolved by content.

Currently quoted scalars whose contents look numeric are reclassified as numbers:

  version: "1.11"      # parsed as Float 1.11, should be String "1.11"
  post-code: "02139"   # parsed as Int 2139, should be String "02139"
  keywords:
    - "4"              # parsed as Int 4, should be String "4"

Direct Codec.String paths in the streaming decoder were unaffected because they bind the value via Cursor.next without going through classify_scalar.

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:nhyitepp3u4u6fcfboegzcjw/sh.tangled.repo.pull/3mksmbkhn6322
+25 -21
Diff #0
+25 -21
ocaml-yaml/lib/yaml.ml
··· 116 116 loop () 117 117 end 118 118 119 - let classify_scalar s = 119 + let classify_scalar ?(style = `Plain) s = 120 120 (* YAML 1.2 core schema resolution (simplified): try int, then float, 121 - then bool / null, fall through to string. *) 122 - match s with 123 - | "" | "~" | "null" | "Null" | "NULL" -> Value.null () 124 - | "true" | "True" | "TRUE" -> Value.bool true 125 - | "false" | "False" | "FALSE" -> Value.bool false 126 - | ".inf" | ".Inf" | ".INF" -> Value.float Float.infinity 127 - | "+.inf" | "+.Inf" | "+.INF" -> Value.float Float.infinity 128 - | "-.inf" | "-.Inf" | "-.INF" -> Value.float Float.neg_infinity 129 - | ".nan" | ".NaN" | ".NAN" -> Value.float Float.nan 130 - | _ -> ( 131 - match Int64.of_string_opt s with 132 - | Some i -> Value.int i 133 - | None -> ( 134 - match Float.of_string_opt s with 135 - | Some f -> Value.float f 136 - | None -> Value.string s)) 121 + then bool / null, fall through to string. Per YAML 1.2.2 §10.3.2, 122 + non-plain (quoted/literal/folded) scalars are tagged [!!str] and must 123 + not go through implicit type resolution. *) 124 + if style <> `Plain then Value.string s 125 + else 126 + match s with 127 + | "" | "~" | "null" | "Null" | "NULL" -> Value.null () 128 + | "true" | "True" | "TRUE" -> Value.bool true 129 + | "false" | "False" | "FALSE" -> Value.bool false 130 + | ".inf" | ".Inf" | ".INF" -> Value.float Float.infinity 131 + | "+.inf" | "+.Inf" | "+.INF" -> Value.float Float.infinity 132 + | "-.inf" | "-.Inf" | "-.INF" -> Value.float Float.neg_infinity 133 + | ".nan" | ".NaN" | ".NAN" -> Value.float Float.nan 134 + | _ -> ( 135 + match Int64.of_string_opt s with 136 + | Some i -> Value.int i 137 + | None -> ( 138 + match Float.of_string_opt s with 139 + | Some f -> Value.float f 140 + | None -> Value.string s)) 137 141 138 142 (* Read one complete YAML value from a cursor into a materialised 139 143 [Value.t]. Anchors encountered on the way are recorded in [anchors]; ··· 180 184 | None -> Error.fail Meta.none "unterminated mapping" 181 185 in 182 186 remember anchor (Value.mapping (pairs [])) 183 - | Some (Event.Scalar { anchor; value = s; tag = _; style = _; _ }) -> 187 + | Some (Event.Scalar { anchor; value = s; tag = _; style; _ }) -> 184 188 Cursor.drop cur; 185 - remember anchor (classify_scalar s) 189 + remember anchor (classify_scalar ~style s) 186 190 | Some (Event.Alias { anchor }) -> ( 187 191 Cursor.drop cur; 188 192 match Hashtbl.find_opt anchors anchor with ··· 313 317 let v = Value.mapping (pairs []) in 314 318 record_anchor anchor v; 315 319 v 316 - | Some (Event.Scalar { anchor; value = s; _ }) -> 320 + | Some (Event.Scalar { anchor; value = s; style; _ }) -> 317 321 Cursor.drop cur; 318 - let v = classify_scalar s in 322 + let v = classify_scalar ~style s in 319 323 record_anchor anchor v; 320 324 v 321 325 | Some (Event.Alias { anchor }) -> (

History

1 round 0 comments
sign up or login to add to the discussion
anil.recoil.org submitted #0
1 commit
expand
cdc73c58
Fix implicit scalar conversion to numbers
merge conflicts detected
expand
  • ocaml-yaml/lib/yaml.ml:116
expand 0 comments