Skip to content

Commit 048b824

Browse files
authored
Merge pull request #6611 from diffblue/argc-may-be-zero
argc may be zero
2 parents 5917ab4 + 788cb49 commit 048b824

File tree

8 files changed

+47
-18
lines changed

8 files changed

+47
-18
lines changed

regression/cbmc/argc-and-argv/argc1.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
int main(int argc, char **argv)
2+
{
3+
// There is no guarantee that there is at least one, so this
4+
// program is not memory safe.
5+
int n;
6+
7+
for(n = 1; n < argc; n++)
8+
{
9+
// nothing
10+
}
11+
12+
char *path = argv[n]; // out-of-bounds when argc == 0
13+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
argc1.c
3+
--bounds-check --pointer-check --unwind 0
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[.*\] line .* dereference failure: pointer outside object bounds in argv\[.*n\]: FAILURE$
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring

regression/cbmc/argc-and-argv/argv1.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
int main(int main_argc, char **main_argv)
2+
{
3+
char *x;
4+
5+
// there is no guarantee that there is at least one,
6+
// but note that argv is NULL-terminated
7+
x = main_argv[0];
8+
assert(main_argc >= 0);
9+
10+
// last one must be NULL
11+
assert(main_argv[main_argc] == 0);
12+
}

regression/cbmc/argv1/test.desc renamed to regression/cbmc/argc-and-argv/argv1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CORE
2-
main.c
2+
argv1.c
33
--bounds-check --pointer-check
44
^EXIT=0$
55
^SIGNAL=0$

regression/cbmc/argv1/main.c

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

regression/cbmc/lhs-pointer-aliases-constant/test.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include <assert.h>
22

3-
int main(int argc, char **argv)
3+
int main()
44
{
55
int x;
66
const char *c = "Hello world";
7+
_Bool dummy;
8+
__CPROVER_assume(dummy);
79

8-
int *p = (argc ? &x : (int *)c);
10+
int *p = (dummy ? &x : (int *)c);
911

1012
*p = 1;
1113

regression/cbmc/multiple-goto-traces/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ int main(int argc, char **argv)
55
assert(4 != argc);
66
argc++;
77
argc--;
8-
assert(argc >= 1);
8+
assert(argc >= 0);
99
assert(argc != 4);
1010
argc++;
1111
argc--;

src/ansi-c/ansi_c_entry_point.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,15 @@ bool generate_ansi_c_start_function(
304304
const symbolt &argv_symbol=ns.lookup("argv'");
305305

306306
{
307-
// assume argc is at least one
308-
exprt one=from_integer(1, argc_symbol.type);
307+
// Assume argc is at least zero. Note that we don't assume it's
308+
// at least one, since this isn't guaranteed, as exemplified by
309+
// https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt
310+
// The C standard only guarantees "The value of argc shall be
311+
// nonnegative." and "argv[argc] shall be a null pointer."
312+
exprt zero = from_integer(0, argc_symbol.type);
309313

310314
binary_relation_exprt ge(
311-
argc_symbol.symbol_expr(), ID_ge, std::move(one));
315+
argc_symbol.symbol_expr(), ID_ge, std::move(zero));
312316

313317
init_code.add(code_assumet(std::move(ge)));
314318
}

0 commit comments

Comments
 (0)