Last year’s wave of major network security vulnerabilities has kept adversarial testing on my mind. Security auditing tools can discover bugs which are missed during more general testing. In particular, my interest was piqued by American fuzzy lop, a fuzzer released by the Google security team, and I’ve been waiting for the right project to try it out. Read more on Fuzz Testing with afl-fuzz (American Fuzzy Lop)…
Our tests were crashing. They ran fine individually, but when run as a group, certain tests sometimes failed with a spectacular memory access error.
After experimenting with skipping some of the tests, I was able to narrow it down to tests that ran immediately after some database calls. (This was a mobile project for iOS, and we were using Realm.)
While testing our iOS app, my team found a puzzling bug—repeatedly clicking some of the buttons on the main dashboard caused the whole row of buttons to gradually drift up or down, even off the bottom of the screen. It didn’t always move, but once it started moving, it tended to keep sliding in the same direction.
I’ve been working on a multi-threaded, distributed system, and there have been some bugs that only manifested when things lined up exactly right. While the project’s deterministic elements have lots of unit and system tests, every once in a while mysterious failures have appeared.
On top of the other tests, the code is full of asserts for numerous boundary conditions, and stress tests intentionally overload the system in several ways trying to see if they trigger. While the system is generally stable, every once in a while something has still happened due to unusual thread interleaving or network timing, and these issues can be extraordinarily difficult to reproduce. Read more on autoclave: A Pressure Cooker for Programs…
Ansible is a configuration management tool that uses “playbooks”, special scripts that describe an intended configuration (rather than operations to get there), and “modules”, which make changes to reflect the playbook’s configuration. (For example, “runit should be present”, rather than “install runit”.) Read more on Configuring a Git-Controlled Home Directory with Ansible…
A couple of days ago, I read something that stuck in my mind:
“Monitoring trick: Add a line to the beginning of your runit run scripts
to bump a counter. Alert when the derivative is unreasonably high.” –
@nrr, 4:05 PM – 2 Nov 2014
While working on a library for property-based testing in C, I discovered a trick that can be used to make significantly nicer library interfaces in C99: “designated initializers”. As of C99, struct literals can have their fields set by name, in any order. The C99 standard explicitly updated the behavior for how fields in struct literals are handled:
6.7.8 point 21:
“If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.” (emphasis mine)
Since memory with static storage duration is already initialized to zero, this means that in C99 we can finally depend on stack-allocated structs’ fields being set to zero, rather than garbage data from previous stack frames. This is a huge improvement! If pointers to structs are used as arguments for function calls, it also gives C99 a portable way of using optional and keyword arguments. Read more on Nicer C99 APIs with Designated Initializers…
Recently, I discovered a bug in my heatshrink data compression library, a result of a hidden assumption — I expected that input to uncompress would be padded with ‘0’ bits (like its compressed output), but if given trailing ‘1’ bits, it could get stuck: it detected that processing was incomplete, but polling for more output made no further progress.
Finding good test input can be tricky. Even with loads of unit tests, bugs still get through.
Consider a wear-leveling algorithm for flash memory — it takes a series of write operations and spreads them over the flash, because individual blocks can only be written and erased so many times before they wear out. If any write sequence leads to writes concentrating in specific blocks, something isn’t working.
Part 2 finished with the radio receiver circuit’s data made available via a UART-to-USB bridge and a libftdi-based client on the host computer. The data may be available on the network now, but how do people access it?