From: Matthias Schwarzott Date: Sat, 23 Aug 2025 11:37:46 +0000 (+0200) Subject: Bug 508777 - amd64-linux: add minimal scalar test X-Git-Tag: VALGRIND_3_26_0~184 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=446ee179cec7dae91534bb781ef3defae26a4e10;p=thirdparty%2Fvalgrind.git Bug 508777 - amd64-linux: add minimal scalar test --- diff --git a/.gitignore b/.gitignore index 569a8fd5c..80924f997 100644 --- a/.gitignore +++ b/.gitignore @@ -1102,6 +1102,7 @@ /memcheck/tests/amd64-linux/defcfaexpr /memcheck/tests/amd64-linux/int3-amd64 /memcheck/tests/amd64-linux/reallocarray +/memcheck/tests/amd64-linux/scalar /memcheck/tests/amd64-linux/Makefile /memcheck/tests/amd64-linux/Makefile.in diff --git a/NEWS b/NEWS index 0d0ed35ba..b3bce5400 100644 --- a/NEWS +++ b/NEWS @@ -87,6 +87,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 508093 VALGRIND_CLO_CHANGE does not update vex_control 508154 PRE(sys_fchownat) not handling VKI_AT_FDCWD 508638 Self-hosting not working on FreeBSD +508777 amd64-linux: add minimal scalar test 508869 x86-linux: simplify scalar test output To see details of a given bug, visit diff --git a/memcheck/tests/amd64-linux/Makefile.am b/memcheck/tests/amd64-linux/Makefile.am index 26e8c8ed5..a3b5df5a6 100644 --- a/memcheck/tests/amd64-linux/Makefile.am +++ b/memcheck/tests/amd64-linux/Makefile.am @@ -2,7 +2,9 @@ include $(top_srcdir)/Makefile.tool-tests.am dist_noinst_SCRIPTS = \ - filter_stderr filter_defcfaexpr + filter_defcfaexpr filter_scalar filter_stderr + +noinst_HEADERS = scalar.h EXTRA_DIST = \ access_below_sp_1.vgtest \ @@ -11,12 +13,14 @@ EXTRA_DIST = \ access_below_sp_2.stderr.exp access_below_sp_2.stdout.exp \ defcfaexpr.vgtest defcfaexpr.stderr.exp \ int3-amd64.vgtest int3-amd64.stderr.exp int3-amd64.stdout.exp \ + scalar.stderr.exp scalar.vgtest \ reallocarray.vgtest reallocarray.stderr.exp check_PROGRAMS = \ access_below_sp \ defcfaexpr \ - int3-amd64 + int3-amd64 \ + scalar if HAVE_REALLOCARRAY check_PROGRAMS += reallocarray @@ -29,3 +33,4 @@ AM_CCASFLAGS += @FLAG_M64@ defcfaexpr_SOURCES = defcfaexpr.S defcfaexpr_CFLAGS = $(AM_CFLAGS) @FLAG_NO_PIE@ reallocarray_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_ALLOC_SIZE_LARGER_THAN@ +scalar_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@ diff --git a/memcheck/tests/amd64-linux/filter_scalar b/memcheck/tests/amd64-linux/filter_scalar new file mode 100755 index 000000000..ee19ffaf2 --- /dev/null +++ b/memcheck/tests/amd64-linux/filter_scalar @@ -0,0 +1,7 @@ +#! /bin/sh + +# remove line numbers as they just cause larger patches +sed "/: main /s/\(scalar.c\):[0-9]*)/\1)/" | + +../filter_stderr "$@" + diff --git a/memcheck/tests/amd64-linux/scalar.c b/memcheck/tests/amd64-linux/scalar.c new file mode 100644 index 000000000..703d46860 --- /dev/null +++ b/memcheck/tests/amd64-linux/scalar.c @@ -0,0 +1,58 @@ +#define _GNU_SOURCE + +#include "../../memcheck.h" +#include "scalar.h" +#include + +// Here we are trying to trigger every syscall error (scalar errors and +// memory errors) for every syscall. We do this by passing a lot of bogus +// arguments, mostly 0 and 1 (often it's 1 because NULL ptr args often aren't +// checked for memory errors, or in order to have a non-zero length used +// with some buffer). So most of the syscalls don't actually succeed and do +// anything. +// +// Occasionally we have to be careful not to cause Valgrind to seg fault in +// its pre-syscall wrappers; it does so because it can't know in general +// when memory is unaddressable, and so tries to dereference it when doing +// PRE_MEM_READ/PRE_MEM_WRITE calls. (Note that Memcheck will +// always issue an error message immediately before these seg faults occur). +// +// The output has numbers like "3s 2m" for each syscall. "s" is short for +// "scalar", ie. the argument itself is undefined. "m" is short for "memory", +// ie. the argument points to memory which is unaddressable. + +int main(void) +{ + // uninitialised, but we know px[0] is 0x0 + long* px = malloc(sizeof(long)); + long x0 = px[0]; + long res; + + // All __NR_xxx numbers are taken from amd64 + + /* Check the syscall number 0 and 1 two trivial generic syscalls. */ + + /* __NR_read 0 */ + /* Nb: here we are also getting an error from the syscall arg itself. */ + GO(__NR_read, "1+3s 1m"); + SY(__NR_read + x0, x0, x0, x0 + 1); FAIL; + + /* __NR_write 1 */ + GO(__NR_write, "3s 1m"); + SY(__NR_write, x0, x0, x0 + 1); FAIL; + + // __NR_exit 60 + GO(__NR_exit, "below"); + // (see below) + + // no such syscall... + GO(9999, "1e"); + SY(9999); FAIL; + + // __NR_exit 1 + GO(__NR_exit, "1s 0m"); + SY(__NR_exit, x0); FAIL; + + assert(0); +} + diff --git a/memcheck/tests/amd64-linux/scalar.h b/memcheck/tests/amd64-linux/scalar.h new file mode 100644 index 000000000..52f742e4a --- /dev/null +++ b/memcheck/tests/amd64-linux/scalar.h @@ -0,0 +1,65 @@ +#include "../../../include/vki/vki-scnums-x86-linux.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __THROW +#define __THROW +#endif + +// Since we use vki_unistd.h, we can't include . So we have to +// declare this ourselves. +extern long int syscall (long int __sysno, ...) __THROW; + +// Thorough syscall scalar arg checking. Also serves as thorough checking +// for (very) basic syscall use. Generally not trying to do anything +// meaningful with the syscalls. + +#define GO(__NR_xxx, s) \ + fprintf(stderr, "-----------------------------------------------------\n" \ + "%3d:%20s %s\n" \ + "-----------------------------------------------------\n", \ + __NR_xxx, #__NR_xxx, s); + +#define SY res = syscall + +#define FAIL assert(-1 == res); +#define SUCC assert(-1 != res); +#define SUCC_OR_FAIL /* no test */ + +#define FAILx(E) \ + do { \ + int myerrno = errno; \ + if (-1 == res) { \ + if (E == myerrno) { \ + /* as expected */ \ + } else { \ + fprintf(stderr, "Expected error %s (%d), got %d\n", #E, E, myerrno); \ + exit(1); \ + } \ + } else { \ + fprintf(stderr, "Expected error %s (%d), got success\n", #E, E); \ + exit(1); \ + } \ + } while (0); + +#define SUCC_OR_FAILx(E) \ + do { \ + int myerrno = errno; \ + if (-1 == res) { \ + if (E == myerrno) { \ + /* as expected */ \ + } else { \ + fprintf(stderr, "Expected error %s (%d), got %d\n", #E, E, myerrno); \ + exit(1); \ + } \ + } \ + } while (0); diff --git a/memcheck/tests/amd64-linux/scalar.stderr.exp b/memcheck/tests/amd64-linux/scalar.stderr.exp new file mode 100644 index 000000000..8f7c3073c --- /dev/null +++ b/memcheck/tests/amd64-linux/scalar.stderr.exp @@ -0,0 +1,62 @@ +----------------------------------------------------- + 0: __NR_read 1+3s 1m +----------------------------------------------------- +Syscall param (syscallno) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param read(fd) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param read(buf) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param read(count) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param read(buf) points to unaddressable byte(s) + ... + by 0x........: main (scalar.c) + Address 0x........ is not stack'd, malloc'd or (recently) free'd + +----------------------------------------------------- + 1: __NR_write 3s 1m +----------------------------------------------------- +Syscall param write(fd) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param write(buf) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param write(count) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + +Syscall param write(buf) points to unaddressable byte(s) + ... + by 0x........: main (scalar.c) + Address 0x........ is not stack'd, malloc'd or (recently) free'd + +----------------------------------------------------- + 60: __NR_exit below +----------------------------------------------------- +----------------------------------------------------- +9999: 9999 1e +----------------------------------------------------- +WARNING: unhandled amd64-linux syscall: 9999 +You may be able to write your own handler. +Read the file README_MISSING_SYSCALL_OR_IOCTL. +Nevertheless we consider this a bug. Please report +it at http://valgrind.org/support/bug_reports.html. +----------------------------------------------------- + 60: __NR_exit 1s 0m +----------------------------------------------------- +Syscall param exit(status) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c) + diff --git a/memcheck/tests/amd64-linux/scalar.vgtest b/memcheck/tests/amd64-linux/scalar.vgtest new file mode 100644 index 000000000..81e72b047 --- /dev/null +++ b/memcheck/tests/amd64-linux/scalar.vgtest @@ -0,0 +1,6 @@ +prog: scalar +# Do not run under root +prereq: [ `id -u` -ne 0 ] +vgopts: -q --error-limit=no +stderr_filter: filter_scalar +args: < scalar.c