mirror of
https://github.com/ioacademy-jikim/debugging
synced 2026-08-30 09:19:28 +00:00
first commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
+1
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
@@ -0,0 +1 @@
|
||||
# dummy
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
|
||||
include $(top_srcdir)/Makefile.tool-tests.am
|
||||
|
||||
dist_noinst_SCRIPTS = filter_stderr filter_add filter_suppgen
|
||||
|
||||
EXTRA_DIST = \
|
||||
is_arch_supported \
|
||||
bad_percentify.vgtest bad_percentify.c \
|
||||
bad_percentify.stdout.exp bad_percentify.stderr.exp-glibc28-amd64 \
|
||||
globalerr.vgtest globalerr.stdout.exp \
|
||||
globalerr.stderr.exp-glibc28-amd64 \
|
||||
globalerr.stderr.exp-gcc491-amd64 \
|
||||
hackedbz2.vgtest hackedbz2.stdout.exp \
|
||||
hackedbz2.stderr.exp-glibc28-amd64 \
|
||||
hsg.vgtest hsg.stdout.exp hsg.stderr.exp \
|
||||
preen_invars.vgtest preen_invars.stdout.exp \
|
||||
preen_invars.stderr.exp-glibc28-amd64 \
|
||||
stackerr.vgtest stackerr.stdout.exp \
|
||||
stackerr.stderr.exp-glibc28-amd64 stackerr.stderr.exp-glibc27-x86
|
||||
|
||||
check_PROGRAMS = \
|
||||
bad_percentify \
|
||||
globalerr hackedbz2 \
|
||||
hsg \
|
||||
preen_invars preen_invars_so.so \
|
||||
stackerr
|
||||
|
||||
# DDD: not sure if these ones should work on Darwin or not... if not, should
|
||||
# be moved into x86-linux/.
|
||||
#if ! VGCONF_OS_IS_DARWIN
|
||||
# check_PROGRAMS += \
|
||||
# ccc
|
||||
#endif
|
||||
|
||||
|
||||
AM_CFLAGS += $(AM_FLAG_M3264_PRI)
|
||||
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
|
||||
|
||||
# To make it a bit more realistic, build hackedbz2.c with at
|
||||
# least some optimisation.
|
||||
hackedbz2_CFLAGS = $(AM_CFLAGS) -O -Wno-inline
|
||||
|
||||
globalerr_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@
|
||||
# C ones
|
||||
#pth_create_LDADD = -lpthread
|
||||
|
||||
# C++ ones
|
||||
#ccc_SOURCES = ccc.cpp
|
||||
|
||||
# Build shared object for preen_invars
|
||||
preen_invars_DEPENDENCIES = preen_invars_so.so
|
||||
if VGCONF_OS_IS_DARWIN
|
||||
preen_invars_LDADD = -ldl
|
||||
preen_invars_LDFLAGS = $(AM_FLAG_M3264_PRI)
|
||||
else
|
||||
preen_invars_LDADD = -ldl
|
||||
preen_invars_LDFLAGS = $(AM_FLAG_M3264_PRI) \
|
||||
-Wl,-rpath,$(top_builddir)/memcheck/tests
|
||||
endif
|
||||
|
||||
preen_invars_so_so_CFLAGS = $(AM_CFLAGS) -fpic
|
||||
if VGCONF_OS_IS_DARWIN
|
||||
preen_invars_so_so_LDFLAGS = -fpic $(AM_FLAG_M3264_PRI) -dynamic \
|
||||
-dynamiclib -all_load
|
||||
else
|
||||
preen_invars_so_so_LDFLAGS = -fpic $(AM_FLAG_M3264_PRI) -shared \
|
||||
-Wl,-soname -Wl,preen_invars_so.so
|
||||
endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,647 @@
|
||||
|
||||
/* This demonstrates a stack overrun bug that exp-ptrcheck found while
|
||||
running Valgrind itself (self hosting). As at 12 Sept 08 this bug
|
||||
is still in Valgrind. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef unsigned long long int ULong;
|
||||
typedef signed long long int Long;
|
||||
typedef unsigned int UInt;
|
||||
typedef signed int Int;
|
||||
typedef signed char Char;
|
||||
typedef char HChar;
|
||||
typedef unsigned long UWord;
|
||||
typedef signed long Word;
|
||||
|
||||
|
||||
|
||||
typedef unsigned char Bool;
|
||||
#define True ((Bool)1)
|
||||
#define False ((Bool)0)
|
||||
|
||||
#define VG_(_str) VG_##_str
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
vg_sprintf, copied from m_libcprint.c
|
||||
------------------------------------------------------------------ */
|
||||
UInt
|
||||
VG_(debugLog_vprintf) (
|
||||
void(*send)(HChar,void*),
|
||||
void* send_arg2,
|
||||
const HChar* format,
|
||||
va_list vargs
|
||||
);
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
printf() and friends
|
||||
------------------------------------------------------------------ */
|
||||
typedef
|
||||
struct { Int fd; Bool is_socket; }
|
||||
OutputSink;
|
||||
|
||||
|
||||
OutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */
|
||||
|
||||
/* Do the low-level send of a message to the logging sink. */
|
||||
static
|
||||
void send_bytes_to_logging_sink ( OutputSink* sink, HChar* msg, Int nbytes )
|
||||
{
|
||||
fwrite(msg, 1, nbytes, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
/* --------- printf --------- */
|
||||
|
||||
typedef
|
||||
struct {
|
||||
HChar buf[512];
|
||||
Int buf_used;
|
||||
OutputSink* sink;
|
||||
}
|
||||
printf_buf_t;
|
||||
|
||||
// Adds a single char to the buffer. When the buffer gets sufficiently
|
||||
// full, we write its contents to the logging sink.
|
||||
static void add_to__printf_buf ( HChar c, void *p )
|
||||
{
|
||||
printf_buf_t *b = (printf_buf_t *)p;
|
||||
|
||||
if (b->buf_used > sizeof(b->buf) - 2 ) {
|
||||
send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
|
||||
b->buf_used = 0;
|
||||
}
|
||||
b->buf[b->buf_used++] = c;
|
||||
b->buf[b->buf_used] = 0;
|
||||
assert(b->buf_used < sizeof(b->buf));
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static UInt vprintf_to_buf ( printf_buf_t* b,
|
||||
const HChar *format, va_list vargs )
|
||||
{
|
||||
UInt ret = 0;
|
||||
if (b->sink->fd >= 0 || b->sink->fd == -2) {
|
||||
ret = VG_(debugLog_vprintf)
|
||||
( add_to__printf_buf, b, format, vargs );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static UInt vprintf_WRK ( OutputSink* sink,
|
||||
const HChar *format, va_list vargs )
|
||||
{
|
||||
printf_buf_t myprintf_buf
|
||||
= { "", 0, sink };
|
||||
UInt ret;
|
||||
ret = vprintf_to_buf(&myprintf_buf, format, vargs);
|
||||
// Write out any chars left in the buffer.
|
||||
if (myprintf_buf.buf_used > 0) {
|
||||
send_bytes_to_logging_sink( myprintf_buf.sink,
|
||||
myprintf_buf.buf,
|
||||
myprintf_buf.buf_used );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
UInt VG_(vprintf) ( const HChar *format, va_list vargs )
|
||||
{
|
||||
return vprintf_WRK( &VG_(log_output_sink), format, vargs );
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
UInt VG_(printf) ( const HChar *format, ... )
|
||||
{
|
||||
UInt ret;
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
ret = VG_(vprintf)(format, vargs);
|
||||
va_end(vargs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Bool toBool ( Int x ) {
|
||||
Int r = (x == 0) ? False : True;
|
||||
return (Bool)r;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static Int local_strlen ( const HChar* str )
|
||||
{
|
||||
Int i = 0;
|
||||
while (str[i] != 0) i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static HChar local_toupper ( HChar c )
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c + ('A' - 'a');
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
/*--- A simple, generic, vprintf implementation. ---*/
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
/* -----------------------------------------------
|
||||
Distantly derived from:
|
||||
|
||||
vprintf replacement for Checker.
|
||||
Copyright 1993, 1994, 1995 Tristan Gingold
|
||||
Written September 1993 Tristan Gingold
|
||||
Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
|
||||
|
||||
(Checker itself was GPL'd.)
|
||||
----------------------------------------------- */
|
||||
|
||||
/* Some flags. */
|
||||
#define VG_MSG_SIGNED 1 /* The value is signed. */
|
||||
#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
|
||||
#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
|
||||
#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
|
||||
#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
|
||||
#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
|
||||
|
||||
/* Copy a string into the buffer. */
|
||||
static __attribute__((noinline))
|
||||
UInt myvprintf_str ( void(*send)(HChar,void*),
|
||||
void* send_arg2,
|
||||
Int flags,
|
||||
Int width,
|
||||
HChar* str,
|
||||
Bool capitalise )
|
||||
{
|
||||
# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
|
||||
UInt ret = 0;
|
||||
Int i, extra;
|
||||
Int len = local_strlen(str);
|
||||
|
||||
if (width == 0) {
|
||||
ret += len;
|
||||
for (i = 0; i < len; i++)
|
||||
send(MAYBE_TOUPPER(str[i]), send_arg2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (len > width) {
|
||||
ret += width;
|
||||
for (i = 0; i < width; i++)
|
||||
send(MAYBE_TOUPPER(str[i]), send_arg2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extra = width - len;
|
||||
if (flags & VG_MSG_LJUSTIFY) {
|
||||
ret += extra;
|
||||
for (i = 0; i < extra; i++)
|
||||
send(' ', send_arg2);
|
||||
}
|
||||
ret += len;
|
||||
for (i = 0; i < len; i++)
|
||||
send(MAYBE_TOUPPER(str[i]), send_arg2);
|
||||
if (!(flags & VG_MSG_LJUSTIFY)) {
|
||||
ret += extra;
|
||||
for (i = 0; i < extra; i++)
|
||||
send(' ', send_arg2);
|
||||
}
|
||||
|
||||
# undef MAYBE_TOUPPER
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Copy a string into the buffer, escaping bad XML chars. */
|
||||
static
|
||||
UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
|
||||
void* send_arg2,
|
||||
HChar* str )
|
||||
{
|
||||
UInt ret = 0;
|
||||
Int i;
|
||||
Int len = local_strlen(str);
|
||||
HChar* alt;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
switch (str[i]) {
|
||||
case '&': alt = "&"; break;
|
||||
case '<': alt = "<"; break;
|
||||
case '>': alt = ">"; break;
|
||||
default: alt = NULL;
|
||||
}
|
||||
|
||||
if (alt) {
|
||||
while (*alt) {
|
||||
send(*alt, send_arg2);
|
||||
ret++;
|
||||
alt++;
|
||||
}
|
||||
} else {
|
||||
send(str[i], send_arg2);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Write P into the buffer according to these args:
|
||||
* If SIGN is true, p is a signed.
|
||||
* BASE is the base.
|
||||
* If WITH_ZERO is true, '0' must be added.
|
||||
* WIDTH is the width of the field.
|
||||
*/
|
||||
static
|
||||
UInt myvprintf_int64 ( void(*send)(HChar,void*),
|
||||
void* send_arg2,
|
||||
Int flags,
|
||||
Int base,
|
||||
Int width,
|
||||
Bool capitalised,
|
||||
ULong p )
|
||||
{
|
||||
HChar buf[40];
|
||||
Int ind = 0;
|
||||
Int i, nc = 0;
|
||||
Bool neg = False;
|
||||
HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
UInt ret = 0;
|
||||
|
||||
if (base < 2 || base > 16)
|
||||
return ret;
|
||||
|
||||
if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
|
||||
p = - (Long)p;
|
||||
neg = True;
|
||||
}
|
||||
|
||||
if (p == 0)
|
||||
buf[ind++] = '0';
|
||||
else {
|
||||
while (p > 0) {
|
||||
if (flags & VG_MSG_COMMA && 10 == base &&
|
||||
0 == (ind-nc) % 3 && 0 != ind)
|
||||
{
|
||||
buf[ind++] = ',';
|
||||
nc++;
|
||||
}
|
||||
buf[ind++] = digits[p % base];
|
||||
p /= base;
|
||||
}
|
||||
}
|
||||
|
||||
if (neg)
|
||||
buf[ind++] = '-';
|
||||
|
||||
if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
|
||||
for(; ind < width; ind++) {
|
||||
/* assert(ind < 39); */
|
||||
if (ind > 39) {
|
||||
buf[39] = 0;
|
||||
break;
|
||||
}
|
||||
buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/* Reverse copy to buffer. */
|
||||
ret += ind;
|
||||
for (i = ind -1; i >= 0; i--) {
|
||||
send(buf[i], send_arg2);
|
||||
}
|
||||
if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
|
||||
for(; ind < width; ind++) {
|
||||
ret++;
|
||||
/* Never pad with zeroes on RHS -- changes the value! */
|
||||
send(' ', send_arg2);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* A simple vprintf(). */
|
||||
/* EXPORTED */
|
||||
__attribute__((noinline))
|
||||
UInt
|
||||
VG_(debugLog_vprintf) (
|
||||
void(*send)(HChar,void*),
|
||||
void* send_arg2,
|
||||
const HChar* format,
|
||||
va_list vargs
|
||||
)
|
||||
{
|
||||
UInt ret = 0;
|
||||
Int i;
|
||||
Int flags;
|
||||
Int width;
|
||||
Int n_ls = 0;
|
||||
Bool is_long, caps;
|
||||
|
||||
/* We assume that vargs has already been initialised by the
|
||||
caller, using va_start, and that the caller will similarly
|
||||
clean up with va_end.
|
||||
*/
|
||||
|
||||
for (i = 0; format[i] != 0; i++) {
|
||||
if (format[i] != '%') {
|
||||
send(format[i], send_arg2);
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
/* A '%' has been found. Ignore a trailing %. */
|
||||
if (format[i] == 0)
|
||||
break;
|
||||
if (format[i] == '%') {
|
||||
/* '%%' is replaced by '%'. */
|
||||
send('%', send_arg2);
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
flags = 0;
|
||||
n_ls = 0;
|
||||
width = 0; /* length of the field. */
|
||||
while (1) {
|
||||
switch (format[i]) {
|
||||
case '(':
|
||||
flags |= VG_MSG_PAREN;
|
||||
break;
|
||||
case ',':
|
||||
case '\'':
|
||||
/* If ',' or '\'' follows '%', commas will be inserted. */
|
||||
flags |= VG_MSG_COMMA;
|
||||
break;
|
||||
case '-':
|
||||
/* If '-' follows '%', justify on the left. */
|
||||
flags |= VG_MSG_LJUSTIFY;
|
||||
break;
|
||||
case '0':
|
||||
/* If '0' follows '%', pads will be inserted. */
|
||||
flags |= VG_MSG_ZJUSTIFY;
|
||||
break;
|
||||
case '#':
|
||||
/* If '#' follows '%', alternative format will be used. */
|
||||
flags |= VG_MSG_ALTFORMAT;
|
||||
break;
|
||||
default:
|
||||
goto parse_fieldwidth;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
parse_fieldwidth:
|
||||
/* Compute the field length. */
|
||||
while (format[i] >= '0' && format[i] <= '9') {
|
||||
width *= 10;
|
||||
width += format[i++] - '0';
|
||||
}
|
||||
while (format[i] == 'l') {
|
||||
i++;
|
||||
n_ls++;
|
||||
}
|
||||
|
||||
// %d means print a 32-bit integer.
|
||||
// %ld means print a word-size integer.
|
||||
// %lld means print a 64-bit integer.
|
||||
if (0 == n_ls) { is_long = False; }
|
||||
else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
|
||||
else { is_long = True; }
|
||||
|
||||
switch (format[i]) {
|
||||
case 'o': /* %o */
|
||||
if (flags & VG_MSG_ALTFORMAT) {
|
||||
ret += 2;
|
||||
send('0',send_arg2);
|
||||
}
|
||||
if (is_long)
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
|
||||
(ULong)(va_arg (vargs, ULong)));
|
||||
else
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
|
||||
(ULong)(va_arg (vargs, UInt)));
|
||||
break;
|
||||
case 'd': /* %d */
|
||||
flags |= VG_MSG_SIGNED;
|
||||
if (is_long)
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
|
||||
(ULong)(va_arg (vargs, Long)));
|
||||
else
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
|
||||
(ULong)(va_arg (vargs, Int)));
|
||||
break;
|
||||
case 'u': /* %u */
|
||||
if (is_long)
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
|
||||
(ULong)(va_arg (vargs, ULong)));
|
||||
else
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
|
||||
(ULong)(va_arg (vargs, UInt)));
|
||||
break;
|
||||
case 'p':
|
||||
if (format[i+1] == 'S') {
|
||||
i++;
|
||||
/* %pS, like %s but escaping chars for XML safety */
|
||||
/* Note: simplistic; ignores field width and flags */
|
||||
char *str = va_arg (vargs, char *);
|
||||
if (str == (char*) 0)
|
||||
str = "(null)";
|
||||
ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
|
||||
} else {
|
||||
/* %p */
|
||||
ret += 2;
|
||||
send('0',send_arg2);
|
||||
send('x',send_arg2);
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
|
||||
(ULong)((UWord)va_arg (vargs, void *)));
|
||||
}
|
||||
break;
|
||||
case 'x': /* %x */
|
||||
case 'X': /* %X */
|
||||
caps = toBool(format[i] == 'X');
|
||||
if (flags & VG_MSG_ALTFORMAT) {
|
||||
ret += 2;
|
||||
send('0',send_arg2);
|
||||
send('x',send_arg2);
|
||||
}
|
||||
if (is_long)
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
|
||||
(ULong)(va_arg (vargs, ULong)));
|
||||
else
|
||||
ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
|
||||
(ULong)(va_arg (vargs, UInt)));
|
||||
break;
|
||||
case 'c': /* %c */
|
||||
ret++;
|
||||
send(va_arg (vargs, int), send_arg2);
|
||||
break;
|
||||
case 's': case 'S': { /* %s */
|
||||
char *str = va_arg (vargs, char *);
|
||||
if (str == (char*) 0) str = "(null)";
|
||||
ret += myvprintf_str(send, send_arg2,
|
||||
flags, width, str, format[i]=='S');
|
||||
break;
|
||||
}
|
||||
|
||||
// case 'y': { /* %y - print symbol */
|
||||
// Addr a = va_arg(vargs, Addr);
|
||||
//
|
||||
//
|
||||
//
|
||||
// HChar *name;
|
||||
// if (VG_(get_fnname_w_offset)(a, &name)) {
|
||||
// HChar buf[1 + VG_strlen(name) + 1 + 1];
|
||||
// if (flags & VG_MSG_PAREN) {
|
||||
// VG_(sprintf)(str, "(%s)", name):
|
||||
// } else {
|
||||
// VG_(sprintf)(str, "%s", name):
|
||||
// }
|
||||
// ret += myvprintf_str(send, flags, width, buf, 0);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void add_to__sprintf_buf ( HChar c, void *p )
|
||||
{
|
||||
HChar** b = p;
|
||||
*(*b)++ = c;
|
||||
}
|
||||
|
||||
UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
|
||||
{
|
||||
Int ret;
|
||||
HChar* sprintf_ptr = buf;
|
||||
|
||||
ret = VG_(debugLog_vprintf)
|
||||
( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
|
||||
add_to__sprintf_buf('\0', &sprintf_ptr);
|
||||
|
||||
assert(local_strlen(buf) == ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
|
||||
{
|
||||
UInt ret;
|
||||
va_list vargs;
|
||||
va_start(vargs,format);
|
||||
ret = VG_(vsprintf)(buf, format, vargs);
|
||||
va_end(vargs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
percentify()
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
/* This part excerpted from coregrind/m_libcbase.c */
|
||||
|
||||
// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
|
||||
// Right justifies in 'buf'.
|
||||
__attribute__((noinline))
|
||||
void VG_percentify(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
|
||||
{
|
||||
Int i, len, space;
|
||||
ULong p1;
|
||||
HChar fmt[32];
|
||||
|
||||
if (m == 0) {
|
||||
// Have to generate the format string in order to be flexible about
|
||||
// the width of the field.
|
||||
VG_(sprintf)(fmt, "%%-%ds", n_buf);
|
||||
// fmt is now "%<n_buf>s" where <d> is 1,2,3...
|
||||
VG_(sprintf)(buf, fmt, "--%");
|
||||
return;
|
||||
}
|
||||
|
||||
p1 = (100*n) / m;
|
||||
|
||||
if (d == 0) {
|
||||
VG_(sprintf)(buf, "%lld%%", p1);
|
||||
} else {
|
||||
ULong p2;
|
||||
UInt ex;
|
||||
switch (d) {
|
||||
case 1: ex = 10; break;
|
||||
case 2: ex = 100; break;
|
||||
case 3: ex = 1000; break;
|
||||
default: assert(0);
|
||||
/* was: VG_(tool_panic)("Currently can only handle 3 decimal places"); */
|
||||
}
|
||||
p2 = ((100*n*ex) / m) % ex;
|
||||
// Have to generate the format string in order to be flexible about
|
||||
// the width of the post-decimal-point part.
|
||||
VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
|
||||
// fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
|
||||
VG_(sprintf)(buf, fmt, p1, p2);
|
||||
}
|
||||
|
||||
len = local_strlen(buf);
|
||||
space = n_buf - len;
|
||||
if (space < 0) space = 0; /* Allow for v. small field_width */
|
||||
i = len;
|
||||
|
||||
/* Right justify in field */
|
||||
for ( ; i >= 0; i--) buf[i + space] = buf[i];
|
||||
for (i = 0; i < space; i++) buf[i] = ' ';
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
/*--- Stats ---*/
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
/* This part excerpted from coregrind/m_translate.c */
|
||||
|
||||
static UInt n_SP_updates_fast = 0;
|
||||
static UInt n_SP_updates_generic_known = 0;
|
||||
static UInt n_SP_updates_generic_unknown = 0;
|
||||
|
||||
__attribute__((noinline))
|
||||
void VG_print_translation_stats ( void )
|
||||
{
|
||||
HChar buf[6];
|
||||
UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
|
||||
+ n_SP_updates_generic_unknown;
|
||||
VG_percentify(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
|
||||
VG_(printf)(
|
||||
"translate: fast SP updates identified: %'u (%s)\n",
|
||||
n_SP_updates_fast, buf );
|
||||
|
||||
VG_percentify(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
|
||||
VG_(printf)(
|
||||
"translate: generic_known SP updates identified: %'u (%s)\n",
|
||||
n_SP_updates_generic_known, buf );
|
||||
|
||||
VG_percentify(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
|
||||
VG_(printf)(
|
||||
"translate: generic_unknown SP updates identified: %'u (%s)\n",
|
||||
n_SP_updates_generic_unknown, buf );
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main ( void )
|
||||
{
|
||||
VG_print_translation_stats();
|
||||
return 0;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
Invalid read of size 1
|
||||
at 0x........: local_strlen (bad_percentify.c:138)
|
||||
by 0x........: VG_vsprintf (bad_percentify.c:535)
|
||||
by 0x........: VG_sprintf (bad_percentify.c:545)
|
||||
by 0x........: VG_percentify (bad_percentify.c:572)
|
||||
by 0x........: VG_print_translation_stats (bad_percentify.c:625)
|
||||
by 0x........: main (bad_percentify.c:645)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "buf" of size 6 in frame 4 back from here
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid read of size 1
|
||||
at 0x........: local_strlen (bad_percentify.c:138)
|
||||
by 0x........: myvprintf_str (bad_percentify.c:187)
|
||||
by 0x........: VG_debugLog_vprintf (bad_percentify.c:490)
|
||||
by 0x........: vprintf_to_buf (bad_percentify.c:89)
|
||||
by 0x........: vprintf_WRK (bad_percentify.c:102)
|
||||
by 0x........: VG_vprintf (bad_percentify.c:115)
|
||||
by 0x........: VG_printf (bad_percentify.c:124)
|
||||
by 0x........: VG_print_translation_stats (bad_percentify.c:626)
|
||||
by 0x........: main (bad_percentify.c:645)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "buf" of size 6 in frame 7 back from here
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
|
||||
ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1,3 @@
|
||||
translate: fast SP updates identified: 0 ( --%)
|
||||
translate: generic_known SP updates identified: 0 ( --%)
|
||||
translate: generic_unknown SP updates identified: 0 ( --%)
|
||||
@@ -0,0 +1,2 @@
|
||||
prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
|
||||
prog: bad_percentify
|
||||
@@ -0,0 +1,8 @@
|
||||
#! /bin/sh
|
||||
|
||||
dir=`dirname $0`
|
||||
|
||||
$dir/filter_stderr |
|
||||
|
||||
# Anonymise "before" distances (if greater than 9 bytes)
|
||||
sed "s/Address 0x........ is [0-9][0-9]\+ bytes /Address 0x........ is ... bytes /"
|
||||
@@ -0,0 +1,38 @@
|
||||
#! /bin/sh
|
||||
|
||||
dir=`dirname $0`
|
||||
|
||||
$dir/../../tests/filter_stderr_basic |
|
||||
|
||||
# Anonymise addresses
|
||||
$dir/../../tests/filter_addresses |
|
||||
|
||||
# Anonymise paths like "(in /foo/bar/libc-baz.so)"
|
||||
sed "s/(in \/.*libc.*)$/(in \/...libc...)/" |
|
||||
sed "s/(in \/.*libpthread.*)$/(in \/...libpthread...)/" |
|
||||
|
||||
# Anonymise paths like "__libc_start_main (../foo/bar/libc-quux.c:129)"
|
||||
sed "s/__libc_\(.*\) (.*)$/__libc_\1 (...libc...)/" |
|
||||
|
||||
# Remove preambly stuff; also postambly stuff
|
||||
sed \
|
||||
-e "/^exp-sgcheck, a stack and global array overrun detector$/d" \
|
||||
-e "/^NOTE: This is an Experimental-Class Valgrind Tool$/d" \
|
||||
-e "/^Copyright (C) 2003-201., and GNU GPL'd, by OpenWorks Ltd et al.$/d" \
|
||||
-e "/^For counts of detected and suppressed errors, rerun with: -v$/d" |
|
||||
|
||||
# Tidy up in cases where glibc (+ libdl + libpthread + ld) have
|
||||
# been built with debugging information, hence source locs are present.
|
||||
sed \
|
||||
-e "s/ vfprintf (.*)/ .../" \
|
||||
-e "s/ vsprintf (.*)/ .../" \
|
||||
-e "s/ sprintf (.*)/ .../" \
|
||||
-e "s/ printf (.*)/ .../" \
|
||||
-e "s/ strdup (.*)/ .../" \
|
||||
-e "s/(pthread_key_create.c:[0-9]*)/(in \/...libpthread...)/" \
|
||||
-e "s/(genops.c:[0-9]*)/(in \/...libc...)/" \
|
||||
-e "s/(syscall-template.S:[0-9]*)/(in \/...libc...)/" |
|
||||
|
||||
# Anonymise line numbers in h_intercepts.c.
|
||||
sed "s/h_intercepts.c:[0-9]*/h_intercepts.c:.../"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
#! /bin/sh
|
||||
|
||||
dir=`dirname $0`
|
||||
|
||||
$dir/filter_stderr |
|
||||
|
||||
# Anonymise "obj:" path
|
||||
sed "s/obj:.*\/annelid\/tests\/supp/obj:*\/annelid\/tests\/supp/"
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
short a[7];
|
||||
static short b[7];
|
||||
|
||||
int main ( void )
|
||||
{
|
||||
int i;
|
||||
short sum;
|
||||
for (i = 0; i < 7+1; i++) {
|
||||
sum += a[i] * b[i];
|
||||
}
|
||||
return 1 & ((unsigned int)sum / 1000000);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
Invalid read of size 2
|
||||
at 0x........: main (globalerr.c:12)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: global array "a" of size 14 in object with soname "NONE"
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid read of size 2
|
||||
at 0x........: main (globalerr.c:12)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: global array "b" of size 14 in object with soname "NONE"
|
||||
Actual: global array "a" of size 14 in object with soname "NONE"
|
||||
Actual: is 0 after Expected
|
||||
|
||||
|
||||
ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
Invalid read of size 2
|
||||
at 0x........: main (globalerr.c:12)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: global array "a" of size 14 in object with soname "NONE"
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid read of size 2
|
||||
at 0x........: main (globalerr.c:12)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: global array "b" of size 14 in object with soname "NONE"
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
|
||||
ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1,2 @@
|
||||
prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
|
||||
prog: globalerr
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
|
||||
Invalid read of size 1
|
||||
at 0x........: vex_strlen (hackedbz2.c:1006)
|
||||
by 0x........: add_to_myprintf_buf (hackedbz2.c:1284)
|
||||
by 0x........: vex_printf (hackedbz2.c:1155)
|
||||
by 0x........: BZ2_compressBlock (hackedbz2.c:4039)
|
||||
by 0x........: handle_compress (hackedbz2.c:4761)
|
||||
by 0x........: BZ2_bzCompress (hackedbz2.c:4831)
|
||||
by 0x........: BZ2_bzBuffToBuffCompress (hackedbz2.c:5638)
|
||||
by 0x........: main (hackedbz2.c:6484)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: global array "myprintf_buf" of size 70 in object with soname "NONE"
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
|
||||
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1,70 @@
|
||||
22323 bytes read
|
||||
block 1: crc = 0xA212ABF8, combined CRC = 0xA212ABF8, size = 22373
|
||||
too repetitive; using fallback sorting algorithm
|
||||
22373 in block, 13504 after MTF & 1-2 coding, 79+2 syms in use
|
||||
pass 1: size is 17143, grp uses are 38 62 2 92 6 71
|
||||
pass 2: size is 6506, grp uses are 28 71 0 86 9 77
|
||||
pass 3: size is 6479, grp uses are 26 70 0 81 11 83
|
||||
pass 4: size is 6469, grp uses are 26 69 0 74 17 85
|
||||
bytes: mapping 19, selectors 66, code lengths 134, codes 6465
|
||||
final combined CRC = 0xA212ABF8
|
||||
6710 after compression
|
||||
bit 0 -5 DATA_ERROR_MAGIC
|
||||
bit 1 -5 DATA_ERROR_MAGIC
|
||||
bit 2 -5 DATA_ERROR_MAGIC
|
||||
bit 3 -5 DATA_ERROR_MAGIC
|
||||
bit 4 -5 DATA_ERROR_MAGIC
|
||||
bit 5 -5 DATA_ERROR_MAGIC
|
||||
bit 6 -5 DATA_ERROR_MAGIC
|
||||
bit 7 -5 DATA_ERROR_MAGIC
|
||||
bit 8 -5 DATA_ERROR_MAGIC
|
||||
bit 9 -5 DATA_ERROR_MAGIC
|
||||
bit 10 -5 DATA_ERROR_MAGIC
|
||||
bit 11 -5 DATA_ERROR_MAGIC
|
||||
bit 12 -5 DATA_ERROR_MAGIC
|
||||
bit 13 -5 DATA_ERROR_MAGIC
|
||||
bit 14 -5 DATA_ERROR_MAGIC
|
||||
bit 15 -5 DATA_ERROR_MAGIC
|
||||
bit 16 -5 DATA_ERROR_MAGIC
|
||||
bit 17 -5 DATA_ERROR_MAGIC
|
||||
bit 18 -5 DATA_ERROR_MAGIC
|
||||
bit 19 -5 DATA_ERROR_MAGIC
|
||||
bit 20 -5 DATA_ERROR_MAGIC
|
||||
bit 21 -5 DATA_ERROR_MAGIC
|
||||
bit 22 -5 DATA_ERROR_MAGIC
|
||||
bit 23 -5 DATA_ERROR_MAGIC
|
||||
bit 24 0 OK really ok!
|
||||
bit 25 -5 DATA_ERROR_MAGIC
|
||||
bit 26 -5 DATA_ERROR_MAGIC
|
||||
bit 27 0 OK really ok!
|
||||
bit 28 -5 DATA_ERROR_MAGIC
|
||||
bit 29 -5 DATA_ERROR_MAGIC
|
||||
bit 30 -5 DATA_ERROR_MAGIC
|
||||
bit 31 -5 DATA_ERROR_MAGIC
|
||||
bit 32 -4 DATA_ERROR
|
||||
bit 33 -4 DATA_ERROR
|
||||
bit 34 -4 DATA_ERROR
|
||||
bit 35 -4 DATA_ERROR
|
||||
bit 2412 -4 DATA_ERROR
|
||||
bit 4789 -4 DATA_ERROR
|
||||
bit 7166 -4 DATA_ERROR
|
||||
bit 9543 -4 DATA_ERROR
|
||||
bit 11920 -4 DATA_ERROR
|
||||
bit 14297 -4 DATA_ERROR
|
||||
bit 16674 -4 DATA_ERROR
|
||||
bit 19051 -4 DATA_ERROR
|
||||
bit 21428 -4 DATA_ERROR
|
||||
bit 23805 -4 DATA_ERROR
|
||||
bit 26182 -4 DATA_ERROR
|
||||
bit 28559 -4 DATA_ERROR
|
||||
bit 30936 -4 DATA_ERROR
|
||||
bit 33313 -4 DATA_ERROR
|
||||
bit 35690 -4 DATA_ERROR
|
||||
bit 38067 -4 DATA_ERROR
|
||||
bit 40444 -4 DATA_ERROR
|
||||
bit 42821 -4 DATA_ERROR
|
||||
bit 45198 -4 DATA_ERROR
|
||||
bit 47575 -4 DATA_ERROR
|
||||
bit 49952 -4 DATA_ERROR
|
||||
bit 52329 -4 DATA_ERROR
|
||||
all ok
|
||||
@@ -0,0 +1,2 @@
|
||||
prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
|
||||
prog: hackedbz2
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
/* A simple test to demonstrate heap, stack, and global overrun
|
||||
detection. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
short ga[100];
|
||||
|
||||
__attribute__((noinline))
|
||||
int addup_wrongly ( short* arr )
|
||||
{
|
||||
int sum = 0, i;
|
||||
for (i = 0; i <= 100; i++)
|
||||
sum += (int)arr[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
int do_other_stuff ( void )
|
||||
{
|
||||
short la[100];
|
||||
return 123 + addup_wrongly(la);
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
int do_stupid_malloc_stuff ( void )
|
||||
{
|
||||
int sum = 0;
|
||||
unsigned char* duh = malloc(100 * sizeof(char));
|
||||
sum += duh[-1];
|
||||
free(duh);
|
||||
sum += duh[50];
|
||||
return sum;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{
|
||||
long s = addup_wrongly(ga);
|
||||
s += do_other_stuff();
|
||||
s += do_stupid_malloc_stuff();
|
||||
if (s == 123456789) {
|
||||
fprintf(stdout, "well, i never!\n");
|
||||
} else {
|
||||
fprintf(stdout, "boringly as expected\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<valgrindoutput>
|
||||
|
||||
<protocolversion>4</protocolversion>
|
||||
<protocoltool>exp-sgcheck</protocoltool>
|
||||
|
||||
<preamble>
|
||||
<line>...</line>
|
||||
<line>...</line>
|
||||
<line>...</line>
|
||||
<line>...</line>
|
||||
<line>...</line>
|
||||
</preamble>
|
||||
|
||||
<pid>...</pid>
|
||||
<ppid>...</ppid>
|
||||
<tool>exp-sgcheck</tool>
|
||||
|
||||
<args>
|
||||
<vargv>...</vargv>
|
||||
<argv>
|
||||
<exe>./hsg</exe>
|
||||
</argv>
|
||||
</args>
|
||||
|
||||
<status>
|
||||
<state>RUNNING</state>
|
||||
<time>...</time>
|
||||
</status>
|
||||
|
||||
<error>
|
||||
<unique>0x........</unique>
|
||||
<tid>...</tid>
|
||||
<kind>SorG</kind>
|
||||
<what>Invalid read of size 2</what>
|
||||
<stack>
|
||||
<frame>
|
||||
<ip>0x........</ip>
|
||||
<obj>...</obj>
|
||||
<fn>addup_wrongly</fn>
|
||||
<dir>...</dir>
|
||||
<file>hsg.c</file>
|
||||
<line>...</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x........</ip>
|
||||
<obj>...</obj>
|
||||
<fn>main</fn>
|
||||
<dir>...</dir>
|
||||
<file>hsg.c</file>
|
||||
<line>...</line>
|
||||
</frame>
|
||||
</stack>
|
||||
<auxwhat>Address 0x........ expected vs actual:</auxwhat>
|
||||
<auxwhat>Expected: global array "ga" of size 200 in object with soname "NONE"</auxwhat>
|
||||
<auxwhat>Actual: unknown</auxwhat>
|
||||
</error>
|
||||
|
||||
<error>
|
||||
<unique>0x........</unique>
|
||||
<tid>...</tid>
|
||||
<kind>SorG</kind>
|
||||
<what>Invalid read of size 2</what>
|
||||
<stack>
|
||||
<frame>
|
||||
<ip>0x........</ip>
|
||||
<obj>...</obj>
|
||||
<fn>addup_wrongly</fn>
|
||||
<dir>...</dir>
|
||||
<file>hsg.c</file>
|
||||
<line>...</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x........</ip>
|
||||
<obj>...</obj>
|
||||
<fn>do_other_stuff</fn>
|
||||
<dir>...</dir>
|
||||
<file>hsg.c</file>
|
||||
<line>...</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x........</ip>
|
||||
<obj>...</obj>
|
||||
<fn>main</fn>
|
||||
<dir>...</dir>
|
||||
<file>hsg.c</file>
|
||||
<line>...</line>
|
||||
</frame>
|
||||
</stack>
|
||||
<auxwhat>Address 0x........ expected vs actual:</auxwhat>
|
||||
<auxwhat>Expected: stack array "la" of size 200 in frame 1 back from here</auxwhat>
|
||||
<auxwhat>Actual: unknown</auxwhat>
|
||||
</error>
|
||||
|
||||
|
||||
<status>
|
||||
<state>FINISHED</state>
|
||||
<time>...</time>
|
||||
</status>
|
||||
|
||||
<errorcounts>
|
||||
<pair>
|
||||
<count>...</count>
|
||||
<unique>0x........</unique>
|
||||
</pair>
|
||||
<pair>
|
||||
<count>...</count>
|
||||
<unique>0x........</unique>
|
||||
</pair>
|
||||
</errorcounts>
|
||||
|
||||
<suppcounts>...</suppcounts>
|
||||
|
||||
</valgrindoutput>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
boringly as expected
|
||||
@@ -0,0 +1,4 @@
|
||||
prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
|
||||
prog: hsg
|
||||
vgopts: --xml=yes --xml-fd=2 --log-file=/dev/null
|
||||
stderr_filter: ../../memcheck/tests/filter_xml
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Not all architectures are supported by exp-ptr. Currently, PowerPC, s390x,
|
||||
# MIPS and ARM are not supported and will fail these tests as follows:
|
||||
# WARNING: exp-ptrcheck on <blah> platforms: stack and global array
|
||||
# WARNING: checking is not currently supported. Only heap checking is
|
||||
# WARNING: supported.
|
||||
#
|
||||
# So we use this script to prevent these tests from running on unsupported
|
||||
# architectures.
|
||||
|
||||
case `uname -m` in
|
||||
ppc*|arm*|s390x|mips*|tilegx) exit 1;;
|
||||
*) exit 0;;
|
||||
esac
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* see comments in preen_invar_so.c for explanation of this */
|
||||
|
||||
|
||||
int main ( void )
|
||||
{
|
||||
int i, r, sum = 0;
|
||||
char* im_a_global_array;
|
||||
void* hdl = dlopen("./preen_invars_so.so", RTLD_NOW);
|
||||
assert(hdl);
|
||||
im_a_global_array = dlsym(hdl, "im_a_global_array");
|
||||
assert(im_a_global_array);
|
||||
/* printf("%p %p\n", im_a_global_array, me_too_me_too); */
|
||||
|
||||
/* poke around in the global array, so as to cause exp-ptrcheck
|
||||
to generate an Inv_Global invar for it. */
|
||||
for (i = 10/*ERROR*/; i >= 0; i--) {
|
||||
sum += im_a_global_array[i];
|
||||
}
|
||||
/* iterating 10 .. 0 causes an Unknown->Global transition at i = 9.
|
||||
We do it this way in order that at the end of a loop, there is a
|
||||
Global invar in place for the memory read in the loop, so that
|
||||
the subsequent dlclose (hence munmap) causes it to get preened.
|
||||
|
||||
Unfortunately there's nothing to show that the preen was
|
||||
successful or happened at all. The only way to see is from the
|
||||
-v output:
|
||||
|
||||
--686-- sg_: 251 Invars preened, of which 1 changed
|
||||
|
||||
It's the "1 changed" bit which is significant.
|
||||
*/
|
||||
|
||||
/* let's hope gcc is not clever enough to optimise this away, since
|
||||
if it does, then it will also nuke the preceding loop, and
|
||||
thereby render this test program useless. */
|
||||
|
||||
if (sum & 1) printf("%s bar %d\n", "foo", sum & 1); else
|
||||
printf("foo %s %d\n", "bar", 1 - (sum & 1));
|
||||
|
||||
/* Now close (== unmap) the array, so that exp-ptrcheck has to check
|
||||
its collection of Inv_Global invars, and remove this one from
|
||||
it. */
|
||||
r = dlclose(hdl);
|
||||
assert(r == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
Invalid read of size 1
|
||||
at 0x........: main (preen_invars.c:22)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: unknown
|
||||
Actual: global array "im_a_global_arr" of size 10 in object with soname "preen_invars_so"
|
||||
|
||||
|
||||
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1 @@
|
||||
foo bar 1
|
||||
@@ -0,0 +1,2 @@
|
||||
prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
|
||||
prog: preen_invars
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
/* This file contains a global array. It is compiled into a .so,
|
||||
which is dlopened by preen_invar.c. That then accesses the global
|
||||
array, hence generating Inv_Global invariants in sg_main.c.
|
||||
|
||||
preen_invar.c then dlcloses this object, causing it to get
|
||||
unmapped; and we then need to be sure that the Inv_Global is
|
||||
removed by preen_Invars (or, at least, that the system doesn't
|
||||
crash..). */
|
||||
|
||||
char im_a_global_array[10];
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
/* Check basic stack overflow detection.
|
||||
|
||||
It's difficult to get consistent behaviour across all platforms.
|
||||
For example, x86 w/ gcc-4.3.1 gives
|
||||
|
||||
Expected: stack array "a" in frame 2 back from here
|
||||
Actual: stack array "beforea" in frame 2 back from here
|
||||
|
||||
whereas amd64 w/ gcc-4.3.1 gives
|
||||
|
||||
Expected: stack array "a" in frame 2 back from here
|
||||
Actual: unknown
|
||||
|
||||
This happens because on x86 the arrays are placed on the
|
||||
stack without holes in between, but not so for amd64. I don't
|
||||
know why.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
__attribute__((noinline)) void foo ( long* sa, int n )
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
sa[i] = 0;
|
||||
}
|
||||
|
||||
__attribute__((noinline)) void bar ( long* sa, int n )
|
||||
{
|
||||
foo(sa, n);
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{
|
||||
int i;
|
||||
long beforea[3];
|
||||
long a[7];
|
||||
long aftera[3];
|
||||
bar(a, 7+1); /* generates error */
|
||||
bar(a, 7+0); /* generates no error */
|
||||
for (i = 0; i < 7+1; i++) {
|
||||
a[i] = 0;
|
||||
}
|
||||
{char beforebuf[8];
|
||||
char buf[8];
|
||||
char afterbuf[8];
|
||||
sprintf(buf, "%d", 123456789);
|
||||
return 1 & ((a[4] + beforea[1] + aftera[1] + beforebuf[1]
|
||||
+ buf[2] + afterbuf[3]) / 100000) ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
Invalid write of size 4
|
||||
at 0x........: foo (stackerr.c:27)
|
||||
by 0x........: bar (stackerr.c:32)
|
||||
by 0x........: main (stackerr.c:41)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "a" of size 28 in frame 2 back from here
|
||||
Actual: stack array "beforea" of size 12 in frame 2 back from here
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid write of size 4
|
||||
at 0x........: main (stackerr.c:44)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "a" of size 28 in this frame
|
||||
Actual: stack array "beforea" of size 12 in this frame
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x........: _IO_default_xsputn (in /...libc...)
|
||||
by 0x........: ...
|
||||
by 0x........: ...
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "buf" of size 8 in frame 4 back from here
|
||||
Actual: stack array "beforebuf" of size 8 in frame 4 back from here
|
||||
Actual: is 0 after Expected
|
||||
|
||||
|
||||
ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
Invalid write of size 8
|
||||
at 0x........: foo (stackerr.c:27)
|
||||
by 0x........: bar (stackerr.c:32)
|
||||
by 0x........: main (stackerr.c:41)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "a" of size 56 in frame 2 back from here
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid write of size 8
|
||||
at 0x........: main (stackerr.c:44)
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "a" of size 56 in this frame
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x........: _IO_default_xsputn (in /...libc...)
|
||||
by 0x........: ...
|
||||
by 0x........: ...
|
||||
Address 0x........ expected vs actual:
|
||||
Expected: stack array "buf" of size 8 in frame 4 back from here
|
||||
Actual: unknown
|
||||
Actual: is 0 after Expected
|
||||
|
||||
|
||||
ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
|
||||
@@ -0,0 +1,3 @@
|
||||
prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
|
||||
vgopts: --num-callers=3
|
||||
prog: stackerr
|
||||
Reference in New Issue
Block a user