Skip to content

Commit 3648cd7

Browse files
committed
C library/scanf: havoc all target objects
scanf may write to any of the objects behind the pointer-typed arguments.
1 parent 16b84b2 commit 3648cd7

File tree

3 files changed

+49
-9
lines changed

3 files changed

+49
-9
lines changed

regression/cbmc-library/scanf-01/main.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,20 @@
33

44
int main()
55
{
6-
scanf();
7-
assert(0);
6+
scanf(""); // parse nothing, must not result in any out-of-bounds access
7+
int x = 0;
8+
scanf("%d", &x);
9+
_Bool nondet;
10+
if(nondet)
11+
__CPROVER_assert(x == 0, "need not remain zero");
12+
else
13+
__CPROVER_assert(x != 0, "may remain zero");
14+
long int lx = 0;
15+
long long int llx = 0;
16+
scanf("%d, %ld, %lld", &x, &lx, &llx);
17+
if(nondet)
18+
__CPROVER_assert(lx + llx == 0, "need not remain zero");
19+
else
20+
__CPROVER_assert(lx + llx != 0, "may remain zero");
821
return 0;
922
}
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--pointer-check --bounds-check
4-
^EXIT=0$
4+
\[main.assertion.1\] line 11 need not remain zero: FAILURE$
5+
\[main.assertion.2\] line 13 may remain zero: FAILURE$
6+
\[main.assertion.3\] line 18 need not remain zero: FAILURE$
7+
\[main.assertion.4\] line 20 may remain zero: FAILURE$
8+
^\*\* 4 of \d+ failed
9+
^VERIFICATION FAILED$
10+
^EXIT=10$
511
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
712
--
813
^warning: ignoring

src/ansi-c/library/stdio.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,12 @@ int vfscanf(FILE *restrict stream, const char *restrict format, va_list arg)
983983
}
984984

985985
(void)*format;
986-
(void)arg;
986+
while((__CPROVER_size_t)__CPROVER_POINTER_OFFSET(arg) <
987+
__CPROVER_OBJECT_SIZE(arg))
988+
{
989+
void *a = va_arg(arg, void *);
990+
__CPROVER_havoc_object(a);
991+
}
987992

988993
#ifdef __CPROVER_CUSTOM_BITVECTOR_ANALYSIS
989994
__CPROVER_assert(__CPROVER_get_must(stream, "open"),
@@ -1025,7 +1030,12 @@ __CPROVER_HIDE:;
10251030
}
10261031

10271032
(void)*format;
1028-
(void)arg;
1033+
while((__CPROVER_size_t)__CPROVER_POINTER_OFFSET(arg) <
1034+
__CPROVER_OBJECT_SIZE(arg))
1035+
{
1036+
void *a = va_arg(arg, void *);
1037+
__CPROVER_havoc_object(a);
1038+
}
10291039

10301040
#ifdef __CPROVER_CUSTOM_BITVECTOR_ANALYSIS
10311041
__CPROVER_assert(
@@ -1091,7 +1101,13 @@ int vsscanf(const char *restrict s, const char *restrict format, va_list arg)
10911101
int result=__VERIFIER_nondet_int();
10921102
(void)*s;
10931103
(void)*format;
1094-
(void)arg;
1104+
while((__CPROVER_size_t)__CPROVER_POINTER_OFFSET(arg) <
1105+
__CPROVER_OBJECT_SIZE(arg))
1106+
{
1107+
void *a = va_arg(arg, void *);
1108+
__CPROVER_havoc_object(a);
1109+
}
1110+
10951111
return result;
10961112
}
10971113

@@ -1118,7 +1134,13 @@ __CPROVER_HIDE:;
11181134
int result = __VERIFIER_nondet_int();
11191135
(void)*s;
11201136
(void)*format;
1121-
(void)arg;
1137+
while((__CPROVER_size_t)__CPROVER_POINTER_OFFSET(arg) <
1138+
__CPROVER_OBJECT_SIZE(arg))
1139+
{
1140+
void *a = va_arg(arg, void *);
1141+
__CPROVER_havoc_object(a);
1142+
}
1143+
11221144
return result;
11231145
}
11241146

0 commit comments

Comments
 (0)