On Tue, Jun 13, 2006 at 08:28:33PM -0700, Trent Piepho wrote:
> On Wed, 14 Jun 2006, Stephen Thorne wrote:
> > On 6/14/06, Trent Piepho <xyzzy at speakeasy.org> wrote:
> > > p_mapchars isn't a string, it's just two characters with no null termination.
> > > You can't print it with %s.
> >
> > You can't? A quick grep in the source shows 58 occurances of printing
> > p_mapchars with %s.
> All bugs.  Look at struct.h:
> ./struct.h:    char p_mapchars[2];              /* Cache for map window image */

Actually, a grep shows:

include/struct.h:    char p_mapchars[3];                /* Cache for map window image, i.e. "R0" */
ntserv/main.c:    me->p_mapchars[0] = 'X';
ntserv/main.c:    me->p_mapchars[1] = shipnos[pno];
ntserv/main.c:    me->p_mapchars[2] = '\0';

And the various *printf's are of the form:
sprintf(k->p_longname, "%s (%s)", k->p_name, k->p_mapchars);

which are quite legitimate and not bugs at all since the p_mapchars is
NULL teriminated.

The robot code does use a 2 byte local mapchars:
inl.c:    char mapchars[2];

But uses strncpy to copy the local mapchars to the player struct:
inl.c:        STRNCPY(winners[k].mapchars, j->p_mapchars, 2);

I've not bothered looking through the code any further at the moment,
and there may very well be bugs related to improper usage of a non-NULL
terminated mapchars, however I'd have to disagree that all 58 occurances
of printing p_mapchars with %s are bugs.

As for GCC tolerating non-NULL-terminated strings, that's just silly
conjecture.  The compiled program will print characters until it reaches
a NULL or an exception condition at which point a SIGSEGV/SIGILL/etc
signal is raised depending on context.  It is possible due to sheer luck
that buggy *printf code may function correctly as intended because of
compiler behavior in zeroing out unused memory segments (very common in
debug mode), including the unused structure padding bytes in X-byte
aligned architectures.  However, the likelihood of such buggy code to go
undiscovered for years (like Vanilla) is rather small.