Created
February 21, 2012 04:55
-
-
Save maxdeliso/1873806 to your computer and use it in GitHub Desktop.
environ_flood.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*~ *.swp eflood |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
eflood | |
====== | |
This program repeatedly writes environment variables of the form 00000=XXXXX, | |
00001=XXXXX, ... using a call to setenv until the call fails or until the | |
maximum amount of bytes has been written to the environment. Both the length | |
of the name string, which is always padded by zeroes (and therefore always | |
the same length), and the length of the value string, which is always a | |
series of 'X's, must be specified as arguments on the command line. Before | |
each call to setenv the value of the environ pointer is saved, and afterwards | |
it is checked to see whether it had to change. The maximum number of bytes | |
that will be written to the environment is computed beforehand, using the | |
following formula: | |
max = 10 ^ nameSize * ( nameSize + valSize + 1) | |
If the calculation does not cause overflow then the program will terminate | |
when the maximum amount of bytes have been written. Otherwise, the program | |
will loop infinitely. | |
The purpose of the program is to investigate the semantics of setenv as | |
implemented by libc, and to see how it handles a growing environment. Here | |
is a sample run on a 64 bit machine running mac os x. | |
max bytes for sizes 4, 4: 90000 | |
[ n : written ] environ: old environ -> new environ | |
[ 0 : 9 ] environ: 0x7fff5fbff4c0 -> 0x100200010 | |
[ 1 : 18 ] environ: 0x100200010 -> 0x100200120 | |
[ 3 : 36 ] environ: 0x100200120 -> 0x100200230 | |
[ 5 : 54 ] environ: 0x100200230 -> 0x100200350 | |
[ 7 : 72 ] environ: 0x100200350 -> 0x100200120 | |
[ 19 : 180 ] environ: 0x100200120 -> 0x1002002d0 | |
[ 21 : 198 ] environ: 0x1002002d0 -> 0x100200480 | |
[ 23 : 216 ] environ: 0x100200480 -> 0x100200630 | |
[ 25 : 234 ] environ: 0x100200630 -> 0x1002007f0 | |
[ 27 : 252 ] environ: 0x1002007f0 -> 0x100200480 | |
[ 73 : 666 ] environ: 0x100200480 -> 0x1002009c0 | |
[ 75 : 684 ] environ: 0x1002009c0 -> 0x100200d10 | |
[ 77 : 702 ] environ: 0x100200d10 -> 0x100200800 | |
[ 93 : 846 ] environ: 0x100200800 -> 0x100200be0 | |
[ 95 : 864 ] environ: 0x100200be0 -> 0x101000000 | |
[ 97 : 882 ] environ: 0x101000000 -> 0x101000400 | |
[ 161 : 1458 ] environ: 0x101000400 -> 0x101000a00 | |
[ 225 : 2034 ] environ: 0x101000a00 -> 0x101001200 | |
[ 289 : 2610 ] environ: 0x101001200 -> 0x101001c00 | |
[ 353 : 3186 ] environ: 0x101001c00 -> 0x101000000 | |
[ 865 : 7794 ] environ: 0x101000000 -> 0x101002800 | |
[ 929 : 8370 ] environ: 0x101002800 -> 0x101004600 | |
[ 993 : 8946 ] environ: 0x101004600 -> 0x101000000 | |
[ 2209 : 19890 ] environ: 0x101000000 -> 0x101006600 | |
[ 2273 : 20466 ] environ: 0x101006600 -> 0x10100ae00 | |
[ 2337 : 21042 ] environ: 0x10100ae00 -> 0x101000000 | |
[ 5537 : 49842 ] environ: 0x101000000 -> 0x10100f800 | |
[ 5601 : 50418 ] environ: 0x10100f800 -> 0x10101a800 | |
[ 5665 : 50994 ] environ: 0x10101a800 -> 0x101000000 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Author: Max DeLiso <[email protected]> | |
* Purpose: To investigate the semantics of setenv. | |
* Date: 2/20/12 | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <limits.h> | |
#include <stdbool.h> | |
#include <math.h> | |
#define BUILDER_MAX 128 | |
extern char **environ; | |
const char VAL_CHAR = 'X'; | |
int | |
main (int argc, char **argv) | |
{ | |
unsigned long n; | |
unsigned long envNameSize; | |
unsigned long envValSize; | |
unsigned long envWritten; | |
unsigned long maxEnvWritten; | |
char *envNameBuf; | |
char *envValBuf; | |
char **lastEnviron; | |
char builderStr[BUILDER_MAX]; | |
if (argc != 3) | |
{ | |
fprintf (stderr, | |
"usage: %s [name length] [value length]\nhint: try %s 4 4\n", | |
argv[0], argv[0]); | |
exit (1); | |
} | |
envNameSize = strtoul (argv[1], NULL, 10); | |
envValSize = strtoul (argv[2], NULL, 10); | |
#ifndef NDEBUG | |
fprintf (stderr, "nameSize: %lu valSize: %lu\n", envNameSize, envValSize); | |
#endif | |
/* | |
* Allocate space for both buffers, and fill the envValBuf with VAL_CHAR | |
*/ | |
envNameBuf = malloc (envNameSize + 1); | |
envValBuf = malloc (envValSize + 1); | |
if (!envNameBuf || !envValBuf) | |
{ | |
perror ("malloc"); | |
exit (2); | |
} | |
memset (envValBuf, VAL_CHAR, envValSize); | |
/* | |
* Here we build the string which we will use in each call to snprintf in | |
* the main loop, which we want to take the form of '%0[number]lu'. We | |
* then pass n to snprintf using this string we've built as our format | |
* string, which will always be envNameBytes long due to the fact that | |
* the leading 0 is part of the format string argument. We only need to | |
* do this once. | |
*/ | |
(void) snprintf (builderStr, sizeof (builderStr), "%%0%lulu", envNameSize); | |
#ifndef NDEBUG | |
fprintf (stderr, "builderStr: %s\n", builderStr); | |
#endif | |
/* | |
* Here we compute the maximum amount of bytes we will write given the | |
* lengths we've specified for the environment variable name and size, | |
* and check for overflow. | |
*/ | |
maxEnvWritten = | |
pow (10.0f, (float) envNameSize) * (envValSize + envNameSize + 1); | |
if (maxEnvWritten != 0) | |
{ | |
printf ("max bytes for sizes %lu, %lu: %lu\n", envValSize, | |
envNameSize, maxEnvWritten); | |
} | |
else | |
{ | |
printf ("max size overflowed... defaulting to infinite loop\n"); | |
} | |
printf ("[%16s : %-16s] environ: %16s -> %-16s\n\n", | |
"n", "written", "old environ", "new environ"); | |
for (n = 0, envWritten = 0; | |
(maxEnvWritten != 0) ? (envWritten < maxEnvWritten) : (true); ++n) | |
{ | |
(void) snprintf (envNameBuf, envNameSize + 1, builderStr, n); | |
lastEnviron = environ; | |
#ifndef NDEBUG | |
fprintf (stderr, "name: %s\n val: %s\n n: %lu\n\n", envNameBuf, | |
envValBuf, n); | |
#endif | |
if (setenv (envNameBuf, envValBuf, 1) != 0) | |
{ | |
perror ("setenv"); | |
exit (3); | |
} | |
envWritten += (envNameSize + envValSize + 1); | |
if (environ != lastEnviron) | |
{ | |
printf ("[%16lu : %-16lu] environ: %16p -> %-16p\n", | |
n, envWritten, (void *) lastEnviron, (void *) environ); | |
} | |
} | |
free (envValBuf); | |
free (envNameBuf); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Max DeLiso <[email protected]> | |
.PHONY: clean | |
CC=gcc | |
CFLAGS=-std=c99 -Wall -Wextra -pedantic -O3 -lm -D_POSIX_C_SOURCE=200112L | |
RFLAGS=-DNDEBUG | |
DFLAGS=-g | |
OUT=eflood | |
RM=rm | |
STRIP=strip | |
SOURCE=eflood.c | |
INSTALL=install | |
INSTALLDIR=/usr/local/bin | |
$(OUT): $(SOURCE) | |
@$(CC) $(CFLAGS) $(RFLAGS) $(SOURCE) -o $(OUT) | |
@$(STRIP) $(OUT) | |
debug: $(SOURCE) | |
@$(CC) $(CFLAGS) $(DFLAGS) $(SOURCE) -o $(OUT) | |
clean: | |
@$(RM) -f $(OUT) | |
install: $(OUT) | |
@$(INSTALL) $(OUT) $(INSTALLDIR) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment