Saturday, October 10, 2015

VerySillyMUD: A Lesson About Compiler Warnings

This post is part of my "VerySillyMUD" series, chronicling an attempt to refactor an old MUD into working condition[1].

In our last post, we managed to get the MUD executable to build, and attempted to run it, with somewhat lackluster results:

Fortunately, we get a file and line number with this error, so let's take a look:

Hmm, we seem to not be able to change into whatever directory is represented by dir. Scrolling up through the source we see that this can be set via a command-line argument:

...but we didn't provide one, so it must have a default value. A little further up and we see it gets set to DFLT_DIR; a quick grep gives us:

Aha! It's looking for the "lib" directory, which doesn't exist in the src directory but does exist as a top-level directory in the project. Let's try pointing it there:

Great! There are a lot of error messages in here about "unknown auxiliary codes" but the MUD seems to have started. Let's try to connect as a client:

Ok! Let's proceed and create a character to play:

A quick look over at the terminal where the server was running shows this in the log:

Oh, joy. Looks like we'll have to run this in a debugger to see where it's barfing.

Uh, this is segfaulting in a C library routine? What's going on here? The source code line where this is happening is:

A little more poking around in the debugger shows that all the pointers here (d->pwd, arg, and d->character-> are all well-formated, null-terminated strings. What's going on?

I will spare you, good reader, quite a bit of head scratching and Googling, but here's ultimately what happened: there is no function prototype for crypt() defined or included in this source code file, and the C compiler is making the assumption that it returns an int, which is a 32-bit quantity. In actuality, crypt returns a char *, which on a 64-bit machine like I have, is a 64-bit value; the return value is getting truncated, and when it is likewise passed to strncpy that expects a pointer, we're off again, and the pointer passed in is essentially garbage. Now that I've figured out what the issue is, I would not be surprised if we had a compiler warning about this. Sure enough:

Remember when I said previously that I was generally a fan of "treat compiler warnings as errors"? Looks like I should have taken my own advice. In the next episode, I'll go ahead and clean all of those up.

[1] SillyMUD was a derivative of DikuMUD, which was originally created by Sebastian Hammer, Michael Seifert, Hans Henrik Stærfeldt, Tom Madsen, and Katja Nyboe.