Ever told yourself “oh, I don’t have to sanitize the input because I’m the only person using it” only to have it bite you in the ass?
When I’m loading waypoint data into my database, I calculate the magnetic declination of each point using a program that I got years ago and hacked the hell out of. I call it magvar, because declination is sometimes (incorrectly) called “magnetic variation” and I didn’t know any better when I did it. The program as it was written prompted for input (latitude, longitude, elevation and date) one number at a time, validated it, parsed the World Magnetic Model (WMM) data file, and told you the declination and a bunch of other stuff about the location. Well, I needed it to be faster than that, so I had it pre-parse the WMM file, then it sat there in a loop where it did a "sscanf"
of the four input numbers (C programmers are now shuddering in horror), and printed the output, and then my perl script did an "open2"
to open a pipe to write the four numbers on, and another pipe to read the result. And that’s worked pretty well up until today.
Today I was loading some new datasource, and I noticed that about 75% of the way through, it was hanging. And it appeared to be hanging in the write to the magvar program’s input pipe. I tried commenting out the call, and it ran fine, but of course it didn’t have any declinations. So I put the call back in and ran it again. And then attached to the executable with gdb (some old atrophied skills suddenly got refreshed in memory). And that’s where I discovered that the program seemed to be stuck in a write. And going up a few levels into the code that I’d touched and dumping the local variables, the input latitude and longitude seemed to be indicating a waypoint that was one of the first ones input. That’s when I had another look at the data I was feeding the program. And that’s where I discovered instead of writing 4 doubles that scanf could happily read using "%lf %lf %lf %lf"
, I hadn’t noticed that on some of the waypoints in this new datasource, the elevation was given as "apprx 123"
. I didn’t bother to look in detail what happened at this point, but I assume my unchecked input caused the magvar program to go into an infinite loop, spewing out the same declination value over and over onto the perl program’s input pipe until the pipe filled up.
And I haven’t learned my lesson – I have no plans to fix magvar to validate its input. I’m just going to make sure this particular data loader program does a
$elev =~ s/\s*apprx\s*//;
before calling it.
I am trying to use the same WMM for a project and I cannot get it to compile. GDB indicates there is a problem with the ‘sscanf’ function in geomag.c. I have tried under Tiger and Leopard and even… windows. Can you shed some light on this?
Shawn, the geomag.c program is pretty old. You might need to update the includes a bit. My copy of geomag.c came with two versions, one in a directory called “geomagu” and the other called “geomagp”. The “u” in “geomagu” evidently stands for “unix”, and that’s the one that will probably work better on Mac OS X.
What errors are you getting?
The code compiles but crashes with the error:
worldMag has exited due to signal 10 (SIGBUS).
It seems the line:
fgets(d_str, 80, wmmtemp);
is where it crashes. My copy didn’t come with different directories, only two precompiled binaries (1 for windows and 1 for linux).
The included libraries that came with it are
stdio
stdlib
string
math
(mathimf.h commented out)
I would appreciate any suggestions – I don’t know of anyone else using this on Mac.
I hope you don’t mean that you tried to run one of those two binaries on Mac OS X. The statement it’s crashing in is when it first attempts to read the WMM.COF (previously wmm_95.dat) file. Are you sure you have that file, and it’s in the current directory?
No the binaries are not compiled for OS X. (The windows one does run on an XP machine). I have the WMM.COF file in the same directory and imported into the Xcode project. It is listed as a Unix execution file (in Get Info), however when I open it in AquaMacs it says “DOS format”.
The code that is crashing is when I run what I compiled (geomag.c +WMM.COF). The source compiles successfully but then I get that SIGBUS error and GDB opens up and points to the sscanf line…. Seems like maybe WMM.COF isn’t formatted properly and it isn’t being parsed correctly?