test: Add a test for fortification of string functions
We currently only run the testcase where it doesn't trigger the failed checks though.
This commit is contained in:
1 parent
2013c9c165
commit
4c29469eac
3 files changed
+134
-1
No files matched your search
@@ -160,6 +160,9 @@ RUN cd test && \
|
||||
for test in stacksmash; do \
|
||||
$arch-w64-mingw32-clang $test.c -o $arch/$test.exe -fstack-protector-strong || exit 1; \
|
||||
done; \
|
||||
for test in bufferoverflow; do \
|
||||
$arch-w64-mingw32-clang $test.c -o $arch/$test.exe -lssp -D_FORTIFY_SOURCE=2 -O2 || exit 1; \
|
||||
done; \
|
||||
done
|
||||
|
||||
# Build OpenMP
|
||||
|
||||
+5
-1
@@ -76,6 +76,7 @@ TESTS_CPP_DLL="tlstest-lib throwcatch-lib"
|
||||
TESTS_CPP_LINK_DLL="throwcatch-main"
|
||||
TESTS_SSP="stacksmash"
|
||||
TESTS_ASAN="stacksmash"
|
||||
TESTS_FORTIFY="bufferoverflow"
|
||||
TESTS_UBSAN="ubsan"
|
||||
TESTS_OMP="hello-omp"
|
||||
TESTS_UWP="uwp-error"
|
||||
@@ -162,6 +163,9 @@ for arch in $ARCHS; do
|
||||
for test in $TESTS_SSP; do
|
||||
$arch-w64-mingw32-clang $test.c -o $TEST_DIR/$test.exe -fstack-protector-strong
|
||||
done
|
||||
for test in $TESTS_FORTIFY; do
|
||||
$arch-w64-mingw32-clang $test.c -o $TEST_DIR/$test.exe -O2 -D_FORTIFY_SOURCE=2 -lssp
|
||||
done
|
||||
for test in $TESTS_IDL; do
|
||||
# This is primary a build-only test, so no need to execute it.
|
||||
# The IDL output isn't arch specific, but we want to test the
|
||||
@@ -236,7 +240,7 @@ for arch in $ARCHS; do
|
||||
DLL="$DLL $i"
|
||||
fi
|
||||
done
|
||||
RUN_TESTS="$TESTS_C $TESTS_C_LINK_DLL $TESTS_CPP $TESTS_CPP_LINK_DLL $TESTS_EXTRA $TESTS_SSP"
|
||||
RUN_TESTS="$TESTS_C $TESTS_C_LINK_DLL $TESTS_CPP $TESTS_CPP_LINK_DLL $TESTS_EXTRA $TESTS_SSP $TESTS_FORTIFY"
|
||||
cd $TEST_DIR
|
||||
if [ -n "$COPY" ]; then
|
||||
COPYFILES=""
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Martin Storsjo
|
||||
*
|
||||
* This file is part of llvm-mingw.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(__linux__) || defined(__MINGW32__)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char buf[10];
|
||||
char padding[10];
|
||||
|
||||
const char *ten_chars = "1234567890";
|
||||
int ten = 10;
|
||||
const char *eleven_chars = "1234567890!";
|
||||
int eleven = 11;
|
||||
|
||||
const char *foo = "foo";
|
||||
const char *barbar = "barbar";
|
||||
const char *barbarr = "barbarr";
|
||||
const char *barbarrr = "barbarrr";
|
||||
int six = 6;
|
||||
int seven = 7;
|
||||
int eight = 8;
|
||||
|
||||
char hash = '#';
|
||||
|
||||
#if !defined(__GLIBC__) && !defined(__MINGW32__)
|
||||
#define mempcpy memcpy
|
||||
#endif
|
||||
|
||||
static void acceptable_use(void) {
|
||||
memcpy(buf, ten_chars, ten);
|
||||
memmove(buf, ten_chars, ten);
|
||||
mempcpy(buf, ten_chars, ten);
|
||||
memset(buf, hash, ten);
|
||||
|
||||
// Test writing a full buffer without null termination.
|
||||
strncpy(buf, eleven_chars, ten);
|
||||
|
||||
strcpy(buf, foo);
|
||||
strcat(buf, barbar);
|
||||
|
||||
strcpy(buf, foo);
|
||||
// We copy a truncated amount from the source, and fit exactly in the
|
||||
// buffer.
|
||||
strncat(buf, barbarrr, six);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
#ifndef _FORTIFY_SOURCE
|
||||
fprintf(stderr, "NOTE, this is built without _FORTIFY_SOURCE; the "
|
||||
"checks will fail!\n");
|
||||
#endif
|
||||
if (argc < 2) {
|
||||
acceptable_use();
|
||||
fprintf(stderr, "%s: A test tool for detecting buffer overflows.\n"
|
||||
"Run this with an integer between 1 and 10 to test "
|
||||
"various overflows that should be caught.\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
switch (atoi(argv[1])) {
|
||||
default:
|
||||
case 1:
|
||||
memcpy(buf, eleven_chars, eleven);
|
||||
break;
|
||||
case 2:
|
||||
memmove(buf, eleven_chars, eleven);
|
||||
break;
|
||||
case 3:
|
||||
mempcpy(buf, eleven_chars, eleven);
|
||||
break;
|
||||
case 4:
|
||||
memset(buf, hash, eleven);
|
||||
break;
|
||||
case 5:
|
||||
// The contents of the string fits in the buffer, but the null
|
||||
// terminator doesn't.
|
||||
strcpy(buf, ten_chars);
|
||||
break;
|
||||
case 6:
|
||||
// The contents of the string doesn't fit in the buffer.
|
||||
strncpy(buf, eleven_chars, eleven);
|
||||
break;
|
||||
case 7:
|
||||
strcpy(buf, foo);
|
||||
// The contents of the string fits in the buffer, but the null
|
||||
// terminator doesn't.
|
||||
strcat(buf, barbarr);
|
||||
break;
|
||||
case 8:
|
||||
strcpy(buf, foo);
|
||||
// The contents of the string doesn't fit in the buffer.
|
||||
strcat(buf, barbarrr);
|
||||
break;
|
||||
case 9:
|
||||
strcpy(buf, foo);
|
||||
// We copy a truncated amount from the source, but the null terminator
|
||||
// doesn't fit in the buffer.
|
||||
strncat(buf, barbarrr, seven);
|
||||
break;
|
||||
case 10:
|
||||
strcpy(buf, foo);
|
||||
// The contents of the string doesn't fit in the buffer.
|
||||
strncat(buf, barbarrr, eight);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user