Fix bug in scanf where EOF would be ignored

This commit is contained in:
jD91mZM2
2019-03-28 17:53:44 +01:00
parent 6548aad36d
commit 3f98962054
3 changed files with 60 additions and 20 deletions
+20 -6
View File
@@ -111,6 +111,10 @@ unsafe fn inner_scanf<R: Read>(
}
};
// When an EOF occurs, eof is set, stuff is marked matched
// as usual, and finally it is returned
let mut eof = false;
let mut kind = IntKind::Int;
loop {
kind = match c {
@@ -195,7 +199,7 @@ unsafe fn inner_scanf<R: Read>(
}
width = width.map(|w| w - 1);
if !read!() {
break;
return Ok(matched);
}
if width.map(|w| w > 0).unwrap_or(true)
&& (byte == b'x' || byte == b'X')
@@ -203,7 +207,7 @@ unsafe fn inner_scanf<R: Read>(
radix = 16;
width = width.map(|w| w - 1);
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
break;
return Ok(matched);
}
}
continue;
@@ -215,7 +219,7 @@ unsafe fn inner_scanf<R: Read>(
n.push(byte as char);
width = width.map(|w| w - 1);
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
break;
return Ok(matched);
}
}
@@ -334,6 +338,7 @@ unsafe fn inner_scanf<R: Read>(
}
width = width.map(|w| w - 1);
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
eof = true;
break;
}
}
@@ -352,6 +357,7 @@ unsafe fn inner_scanf<R: Read>(
}
width = width.map(|w| w - 1);
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
eof = true;
break;
}
}
@@ -396,14 +402,18 @@ unsafe fn inner_scanf<R: Read>(
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte)
{
// While we haven't used up all the width, and it matches
while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte) {
if let Some(ref mut ptr) = ptr {
**ptr = byte as c_char;
*ptr = ptr.offset(1);
}
// Decrease the width, and read a new character unless the width is 0
width = width.map(|w| w - 1);
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
// Reading a new character has failed, return after
// actually marking this as matched
eof = true;
break;
}
}
@@ -412,7 +422,7 @@ unsafe fn inner_scanf<R: Read>(
*ptr = 0;
matched += 1;
}
}
},
b'n' => {
if !ignore {
*ap.get::<*mut c_int>() = count as c_int;
@@ -421,6 +431,10 @@ unsafe fn inner_scanf<R: Read>(
_ => return Err(-1),
}
if eof {
return Ok(matched);
}
if width != Some(0) && c != b'n' {
// It didn't hit the width, so an extra character was read and matched.
// But this character did not match so let's reuse it.
+14 -9
View File
@@ -1,9 +1,14 @@
2, { sa: 12, ia: 345, ib: 0, ic: 0, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string: }
3, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string: }
2, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: (nil), char: a, string: }
1, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: a, string: }
1, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: a, string: Hello }
1, { sa: 12, ia: 15, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: a, string: Hello }
2, { sa: 12, ia: 15, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string: elllo }
1, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string: elllo }
0, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string: elllo }
1, { sa: 12, ia: 0, ib: 0, ic: 0, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
2, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
1, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
0, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
1, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: Hello, string2: , string3: , string4: }
1, { sa: 12, ia: 15, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: Hello, string2: , string3: , string4: }
2, { sa: 12, ia: 15, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: elllo, string2: , string3: , string4: }
1, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: elllo, string2: , string3: , string4: }
0, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: elllo, string2: , string3: , string4: }
4, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: e, string2: o, string3: l, string4: d }
4, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: a, string2: e, string3: f, string4: dddddd }
4, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: a, string2: e, string3: f, string4: dddddd }
1, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: testbbbb, string2: e, string3: f, string4: dddddd }
3 "https" "//" "redox-os.org" ""
+26 -5
View File
@@ -12,7 +12,10 @@ struct params {
double da;
int *ptr;
char c;
char string[20];
char string1[20];
char string2[20];
char string3[20];
char string4[20];
};
void test(char* fmt_in, char* input, struct params *p, ...) {
@@ -22,8 +25,8 @@ void test(char* fmt_in, char* input, struct params *p, ...) {
va_end(args);
printf(
"%d, { sa: %hhd, ia: %d, ib: %d, ic: %d, fa: %f, da: %lf, ptr: %p, char: %c, string: %s }\n",
ret, p->sa, p->ia, p->ib, p->ic, p->fa, p->da, p->ptr, p->c, p->string
"%d, { sa: %hhd, ia: %d, ib: %d, ic: %d, fa: %f, da: %lf, ptr: %p, char: %c, string1: %s, string2: %s, string3: %s, string4: %s }\n",
ret, p->sa, p->ia, p->ib, p->ic, p->fa, p->da, p->ptr, p->c, p->string1, p->string2, p->string3, p->string4
);
}
@@ -34,9 +37,27 @@ int main(void) {
test("%x %i %i", "12 0x345 010", &p, &p.ia, &p.ib, &p.ic);
test("%f.%lf", "0.1.0.2", &p, &p.fa, &p.da);
test("%p", "0xABCDEF", &p, &p.ptr);
test("%s", "Hello World", &p, &p.string);
test("%s", "Hello World", &p, &p.string1);
test("%3i", "0xFF", &p, &p.ia);
test("%c%3c", "hello", &p, &p.c, &p.string);
test("%c%3c", "hello", &p, &p.c, &p.string1);
test("test: %2i%n", "test: 0xFF", &p, &p.ia, &p.ib);
test("hello world%%", "hello world%", &p);
test("h%1[ae]ll%1[^a] wor%1[^\n]%[d]", "hello world", &p, &p.string1, &p.string2, &p.string3, &p.string4);
test("h%1[ae]ll%1[^a] wor%1[^\n]%[d]", "halle worfdddddd", &p, &p.string1, &p.string2, &p.string3, &p.string4);
test("h%1[ae]ll%1[^a] wor%1[^\n]%[d]", "halle worfdddddd", &p, &p.string1, &p.string2, &p.string3, &p.string4);
test("%[^a]%[b]", "testbbbb", &p, &p.string1, &p.string2);
// Scanf stolen from the url parsing in curl
char protobuf[16];
char slashbuf[4];
char hostbuf[100];
char pathbuf[100];
int ret = sscanf(
"https://redox-os.org", "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
&protobuf, &slashbuf, &hostbuf, &pathbuf
);
printf("%d \"%s\" \"%s\" \"%s\" \"%s\"\n", ret, &protobuf, &slashbuf, &hostbuf, &pathbuf);
}