summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes2
-rw-r--r--byterun/ints.c23
-rw-r--r--stdlib/scanf.ml3
3 files changed, 17 insertions, 11 deletions
diff --git a/Changes b/Changes
index 1f0bbe639a..15a12be661 100644
--- a/Changes
+++ b/Changes
@@ -45,6 +45,8 @@ Runtime system:
(Peter Zotov, review by Jacques-Henri Jourdan)
Standard library:
+- PR#6316: Scanf.scanf failure on %u formats when reading big integers
+ (Xavier Leroy, BenoƮt Vaugon)
- PR#6390, GPR#36: expose Sys.{int_size,max_wosize} for improved js_of_ocaml portability
(Hugo Heuzard)
* PR#6494: Add equal function in modules
diff --git a/byterun/ints.c b/byterun/ints.c
index ee1f05fa45..fa7aaa3271 100644
--- a/byterun/ints.c
+++ b/byterun/ints.c
@@ -23,6 +23,7 @@
static char * parse_sign_and_base(char * p,
/*out*/ int * base,
+ /*out*/ int * signedness,
/*out*/ int * sign)
{
*sign = 1;
@@ -30,15 +31,17 @@ static char * parse_sign_and_base(char * p,
*sign = -1;
p++;
}
- *base = 10;
+ *base = 10; *signedness = 1;
if (*p == '0') {
switch (p[1]) {
case 'x': case 'X':
- *base = 16; p += 2; break;
+ *base = 16; *signedness = 0; p += 2; break;
case 'o': case 'O':
- *base = 8; p += 2; break;
+ *base = 8; *signedness = 0; p += 2; break;
case 'b': case 'B':
- *base = 2; p += 2; break;
+ *base = 2; *signedness = 0; p += 2; break;
+ case 'u': case 'U':
+ *signedness = 0; p += 2; break;
}
}
return p;
@@ -65,9 +68,9 @@ static intnat parse_intnat(value s, int nbits, const char *errmsg)
{
char * p;
uintnat res, threshold;
- int sign, base, d;
+ int sign, base, signedness, d;
- p = parse_sign_and_base(String_val(s), &base, &sign);
+ p = parse_sign_and_base(String_val(s), &base, &signedness, &sign);
threshold = ((uintnat) -1) / base;
d = parse_digit(*p);
if (d < 0 || d >= base) caml_failwith(errmsg);
@@ -85,7 +88,7 @@ static intnat parse_intnat(value s, int nbits, const char *errmsg)
if (p != String_val(s) + caml_string_length(s)){
caml_failwith(errmsg);
}
- if (base == 10) {
+ if (signedness) {
/* Signed representation expected, allow -2^(nbits-1) to 2^(nbits-1) - 1 */
if (sign >= 0) {
if (res >= (uintnat)1 << (nbits - 1)) caml_failwith(errmsg);
@@ -530,9 +533,9 @@ CAMLprim value caml_int64_of_string(value s)
{
char * p;
uint64_t res, threshold;
- int sign, base, d;
+ int sign, base, signedness, d;
- p = parse_sign_and_base(String_val(s), &base, &sign);
+ p = parse_sign_and_base(String_val(s), &base, &signedness, &sign);
threshold = ((uint64_t) -1) / base;
d = parse_digit(*p);
if (d < 0 || d >= base) caml_failwith(INT64_ERRMSG);
@@ -551,7 +554,7 @@ CAMLprim value caml_int64_of_string(value s)
if (p != String_val(s) + caml_string_length(s)){
caml_failwith(INT64_ERRMSG);
}
- if (base == 10) {
+ if (signedness) {
/* Signed representation expected, allow -2^63 to 2^63 - 1 only */
if (sign >= 0) {
if (res >= (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG);
diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml
index 08fc9aba50..948808830c 100644
--- a/stdlib/scanf.ml
+++ b/stdlib/scanf.ml
@@ -500,7 +500,8 @@ let token_bool ib =
let token_int_literal conv ib =
let tok =
match conv with
- | 'd' | 'i' | 'u' -> Scanning.token ib
+ | 'd' | 'i' -> Scanning.token ib
+ | 'u' -> "0u" ^ Scanning.token ib
| 'o' -> "0o" ^ Scanning.token ib
| 'x' | 'X' -> "0x" ^ Scanning.token ib
| 'b' -> "0b" ^ Scanning.token ib