Shim library for gettimeofday() for testing and exposing time-related bugs.
Presently used to set time to a small distance (10 seconds) before the most recent boundary for overflowing a 32bit representation of time-since-epoch in milliseconds.
This demonstrates using the shim library to expose a bug in w3c from libwww 5.4.0:
LD_PRELOAD=$HOME/src/gtod-shim/gtod.so w3c http://localhost
Looking up localhost
Looking up localhost
Contacting localhost
Segmentation fault
Fortunately, the source code was easy to modify and extend.
make #builds gotd.so
make test #builds the test executable
if you want to read debug lines, open the Makefile and
add -DGTOD_SHIM_DEBUG
to gtod.o:
step.
This is an example of the log you'll read running the commands shown below. emphasis (the separation between logs) is added for clarification, and won't be shown in the actual execution.
[winter@nest] [/dev/pts/3] [master ⚡]
└[~/projects/coolprojects/gtod-shim]> ./test; LD_PRELOAD=./gtod.so ./test
############## normal log #################
1442444777.442752
Operation not permitted
waiting 2 seconds...
(after setting the time) 1442444779.442954
############# shim'd log #####################
[GTOD_HOOK] DELTA_BEFORE_BOUNDARY=0
[GTOD_HOOK] delta to 32bit msec boundary=0ms, reporting time as: Thu Sep 17 01:06:19 2015
1442444779.448548
[STOD_HOOK] called custom settimeofday!
[STOD_HOOK] DELTA_BEFORE_BOUNDARY=102
Operation not permitted
waiting 2 seconds...
[GTOD_HOOK] DELTA_BEFORE_BOUNDARY=102
[GTOD_HOOK] delta to 32bit msec boundary=0ms, reporting time as: Thu Sep 17 01:04:39 2015
(after setting the time) 1442444679.448834
In the shim'd log
, expect the difference between the two times to be
100 seconds: we ask the time to be shifted by 102 seconds, but we also wait (spend) 2 seconds,
so 102-2=100 seconds is the value you'll get.
If you read the Test section, you should've understood how you can preload the shim into your testing application. This section explains how you can leap through time and know where you landed.
This library mocks some functions.
-
int gettimeofday(struct timevalue*, struct timezone*)
this works as explained ingettimeofday(3P)
. if you did not callsettimeofday
before, you'll get the machine time. if you did callsettimeofday
before, the time will be shifted as explained in the following doc. it may crash if you give a non-null value to the second parameter. -
int settimeofday(const struct timevalue*, const struct timezone* tzp)
the time value is ignored. iftzp->tz_dsttime
is equal to 0 (zero), then the time shift is set according to the value oftzp->tz_minuteswest
. Please, please note that the time intzp->tz_minuteswest
is assumed to be in seconds. A positive value means a shift in the past, a negative one a shift in the future. -
time_t time(time_t*)
Simulatestime
fromtime.h
, returning the appropriate time value, in seconds. WARNING: The parameter is ignored, the new value is ALWAYS returned.
Automated testing is here.
To run the tests, just run make run_tests
. This command will take care of Python testing libraries,
building of the shim library and test app building.
Only CPython 3.x is officially supported, support for other implementations/versions
is limited by nose
and sarge
, the two Python dependencies used for the test.
You can find the tests in the tests/
folder.
- compilation fails with libstdc++.a being a broken symlink
Try to replacelibstdc++.a
withlibstdc++.so
. On my machine, it seemed to work.