Skip to content

Commit e41157b

Browse files
committed
C library: implement {v,}snprintf
The model will non-deterministically alter the target string up to the bound given as argument to {v,}snprintf.
1 parent 8560cdc commit e41157b

File tree

5 files changed

+112
-0
lines changed

5 files changed

+112
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <assert.h>
2+
#include <stdio.h>
3+
4+
int main()
5+
{
6+
char result[10];
7+
int bytes = snprintf(result, 10, "%d\n", 42);
8+
assert(bytes <= 10);
9+
return 0;
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--pointer-check --bounds-check --unwind 10 --no-unwinding-assertions
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <assert.h>
2+
#include <stdarg.h>
3+
#include <stdio.h>
4+
5+
int xsnprintf(char *ptr, size_t size, const char *format, ...)
6+
{
7+
va_list list;
8+
va_start(list, format);
9+
int result = vsnprintf(ptr, size, format, list);
10+
va_end(list);
11+
return result;
12+
}
13+
14+
int main()
15+
{
16+
char result[10];
17+
int bytes = xsnprintf(result, 10, "%d\n", 42);
18+
assert(bytes <= 10);
19+
return 0;
20+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--pointer-check --bounds-check --unwind 10 --no-unwinding-assertions
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/ansi-c/library/stdio.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,72 @@ int vasprintf(char **ptr, const char *fmt, va_list ap)
15841584
return i;
15851585
}
15861586

1587+
/* FUNCTION: snprintf */
1588+
1589+
#ifndef __CPROVER_STDIO_H_INCLUDED
1590+
# include <stdio.h>
1591+
# define __CPROVER_STDIO_H_INCLUDED
1592+
#endif
1593+
1594+
#ifndef __CPROVER_STDARG_H_INCLUDED
1595+
# include <stdarg.h>
1596+
# define __CPROVER_STDARG_H_INCLUDED
1597+
#endif
1598+
1599+
int snprintf(char *str, size_t size, const char *fmt, ...)
1600+
{
1601+
va_list list;
1602+
va_start(list, fmt);
1603+
int result = vsnprintf(str, size, fmt, list);
1604+
va_end(list);
1605+
return result;
1606+
}
1607+
1608+
/* FUNCTION: vsnprintf */
1609+
1610+
#ifndef __CPROVER_STDIO_H_INCLUDED
1611+
# include <stdio.h>
1612+
# define __CPROVER_STDIO_H_INCLUDED
1613+
#endif
1614+
1615+
#ifndef __CPROVER_STDARG_H_INCLUDED
1616+
# include <stdarg.h>
1617+
# define __CPROVER_STDARG_H_INCLUDED
1618+
#endif
1619+
1620+
#ifndef __CPROVER_STDLIB_H_INCLUDED
1621+
# include <stdlib.h>
1622+
# define __CPROVER_STDLIB_H_INCLUDED
1623+
#endif
1624+
1625+
char __VERIFIER_nondet_char(void);
1626+
1627+
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
1628+
{
1629+
(void)*fmt;
1630+
1631+
while((__CPROVER_size_t)__CPROVER_POINTER_OFFSET(*(void **)&ap) <
1632+
__CPROVER_OBJECT_SIZE(ap))
1633+
1634+
{
1635+
(void)va_arg(ap, int);
1636+
__CPROVER_precondition(
1637+
__CPROVER_POINTER_OBJECT(str) != __CPROVER_POINTER_OBJECT(ap),
1638+
"vsnprintf object overlap");
1639+
}
1640+
1641+
size_t i = 0;
1642+
for(; i < size; ++i)
1643+
{
1644+
char c = __VERIFIER_nondet_char();
1645+
str[i] = c;
1646+
if(c == '\0')
1647+
break;
1648+
}
1649+
1650+
return i;
1651+
}
1652+
15871653
/* FUNCTION: __acrt_iob_func */
15881654

15891655
#ifdef _WIN32

0 commit comments

Comments
 (0)