#include <stdio.h>
#include <stdlib.h>
void f() {
int i;
int x = 9;
int a[10];
for (i = 0; i < 16; i++)
printf("%2d: Address %x contains %p\n", i, &a[10+i], a[10+i]);
}
int main(void) {
int a = 7;
printf("function main is at address 0x%x\n", &main);
printf("function f is at address 0x%x\n", &f);
f();
return 0;
}
Run at CSE like this
$ gcc-7 invalid0.c -o invalid0
$ ./invalid0
42 42 42 77 77 77 77 77 77 77
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[10];
int b[10];
printf("a[0] is at address %p\n",&a[0]);
printf("a[9] is at address %p\n", &a[9]);
printf("b[0] is at address %p\n",&b[0]);
printf("b[9] is at address %p\n", &b[9]);
for (int i = 0; i < 10; i++) {
a[i] = 77;
}
// loop writes to b[10] .. b[12] which don't exist -
// with gcc 7.3 on x86_64/Linux
// b[12] is stored where a[0] is stored
// with gcc 7 on CSE lab machines
// b[10] is stored where a[0] is stored
for (int i = 0; i <= 12; i++) {
b[i] = 42;
}
// prints 42 77 77 77 77 77 77 77 77 77 on x86_64/Linux
// prints 42 42 42 77 77 77 77 77 77 77 at CSE
for (int i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
Run at CSE like this
$ gcc-7 invalid1.c -o invalid1
$ ./invalid1
42 42 42 77 77 77 77 77 77 77
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i;
int a[10];
printf("i is at address %p\n", &i);
printf("a[0] is at address %p\n", &a[0]);
printf("a[9] is at address %p\n", &a[9]);
printf("a[10] would be stored at address %p\n", &a[10]);
// loop writes to a[10] .. a[11] which don't exist -
// but with gcc 7 on x86_64/Linux
// i would be stored where a[11] is stored
for (i = 0; i <= 11; i++) {
a[i] = 0;
}
return 0;
}
Run at CSE like this
$ gcc-7 invalid2.c -o invalid2
$ ./invalid2
answer=42
#include <stdio.h>
void f(int x);
int main(void) {
int answer = 36;
printf("answer is stored at address %p\n", &answer);
f(5);
printf("answer=%d\n", answer); // prints 42 not 36g
return 0;
}
void f(int x) {
int a[10];
// a[19] doesn't exist
// with gcc-7 at CSE variable answer in main
// happens to be where a[21] would be
// on 64-bit Linux try 19 instead of 21
printf("a[21] would be stored at address %p\n", &a[21]);
a[21] = 42;
}
Run at CSE like this
$ gcc-7 invalid3.c -o invalid3
$ ./invalid3
I will never be printed.
argc was 1
$
#include <stdio.h>
#include <stdlib.h>
void f(void);
void f(void);
int main(int argc, char *argv[]) {
f();
if (argc > 0) {
printf("I will always be printed.\n");
}
if (argc <= 0) {
printf("I will never be printed.\n");
}
printf("argc was %d\n", argc);
return 0;
}
void f() {
int a[10];
// function f has it return address on the stack
// the call of function f from main should return to
// the next statement which is: if (argc > 0)
//
// with gcc7 at CSE f's return address is stored where a[11] would be
//
// so changing a[11] changes where the function returns
//
// adding 28 to a[11] happens to cause it to return several statements later
// at the printf("I will never be printed.\n");
//
// on 64 bit linux machines try instead a[14] += 24
a[11] += 28;
}
Run at CSE like this
$ gcc-7 invalid4.c -o invalid4
$ ./invalid4
authenticated is at address 0xff94bf44
password is at address 0xff94bf3c
Enter your password: 123456789
Welcome. You are authorized.
$
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int authenticated = 0;
char password[8];
printf("authenticated is at address %p\n",&authenticated);
printf("password[8] would be at address %p\n",&password[8]);
printf("Enter your password: ");
int i = 0;
int ch = getchar();
while (ch != '\n' && ch != EOF) {
password[i] = ch;
ch = getchar();
i = i + 1;
}
password[i] = '\0';
if (strcmp(password, "secret") == 0) {
authenticated = 1;
}
// a password longer than 8 characters will overflow the array password
// the variable authenticated is at the address where
// where password[8] would be and gets overwritten
//
// This allows access without knowing the correct password
if (authenticated) {
printf("Welcome. You are authorized.\n");
} else {
printf("Welcome. You are unauthorized. Your death will now be implemented.\n");
printf("Welcome. You will experience a tingling sensation and then death. \n");
printf("Remain calm while your life is extracted.\n");
}
return 0;
}
rm -f tmp.$$
for i in `seq 10 16`
do
for j in `seq 12 32`
do
#echo $i $j
perl -p -e "s/a\[\d+\] \+= \d+/a[$i] += $j/" invalid3.c >tmp.c
gcc-7 tmp.c -o ./tmp.$$
#./tmp.$$ 2>&1
if ./tmp.$$ 2>&1 |egrep always >/dev/null 2>&1
then
echo -n .
continue
fi
if ./tmp.$$ 2>&1 |egrep never
then
echo "code was a[$i] += $j"
exit
else
echo -n +
fi
done
done
rm -f tmp.$$