The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Monday, October 20, 2025

The fix wasn't easy, or C precedence bites

For the past decade now, I've done a Christmas release for mod_blog (only missing the years 2019 and 2023), just beacuse. I was poking around the codebase looking for changes I could make for Christmas this year, and well, I got a bit impatient and have just now released a version in time for Halloween. And it's scary—I'm removing features!

I've removed features in the past, like no longer supporting “ping servers” when it became clear it wasn't worth it, or automatically updating Linked­Tik­Face­My­Insta­Pin­Me­Gram­We­Tok­In­Book­Space­Trest when Insta­Pin­Tik­My­Linked­Face­Me­Trest­Book­Gram­We­In­Space­Tok changed how it works often enough to make it annoying for me to continue. But this time … this time it's different. This is removing functionality that has existed in the code base since the beginning!

To make it easier to write entries, I had code within mod_blog to process the input—mostly what existed was to convert sequences like ``quoted'' to “quoted” and “...” to “…”, but with an option to add <P> tags around logical paragraphs. But given that I now use my own markup language, I rarely used the web interface (like, I can count on my fingers the number of times I've used it and still have a few left over should give an indication of how little I use it) and the code just sat there, unused. So unused that in fixing one bug I introduced another bug in the code I fixed!

To recap, here's the original code:

char UrlDecodeChar(char **psrc)
{
  char *src;
  char  c;
  
  assert(psrc  != NULL);
  assert(*psrc != NULL);
  
  src = *psrc;
  c   = *src++;
  if (c == '+')
    c = ' ';
  else if (c == '%')
  {
    assert(isxdigit(*src));
    assert(isxdigit(*(src+1)));
    c    = ctohex(*src) * 16 + ctohex(*(src+1));
    src += 2;
  }
  *psrc = src;
  return(c);
}

and the “fixed” version:

char UrlDecodeChar(char **psrc)
{
  char *src;
  char  c;
  
  assert(psrc  != NULL);
  assert(*psrc != NULL);
  
  src = *psrc;
  c   = *src++;
  if (c == '+')
    c = ' ';
  else if (c == '%')
  {
    if (!isxdigit(*src))   return '\0';
    if (!isxdigit(*src+1)) return '\0';
    c    = ctohex(*src) * 16 + ctohex(*(src+1));
    src += 2;
  }
  *psrc = src;
  return(c);
}

I don't fault you if you can't spot the bug. I only found it when testing the web interface to ensure it wasn't completely broken with the conversion code removed (instead it's now only mostly broken but that's an interesting case in and of itself and requires its own post). The bug is in this line of code:

if (!isxdigit(*src+1)) return '\0';

The issue is due to C's precedence rules and dereferencing rules. The code above is parsed as src[0] + 1 instead of the src[1] that I was intending. When I modified the function, changing the calls to assert() into actual code to return an error (I typed in the new code as that's faster than modifying the existing code) I … kind of missed that.

Oh, who am I kidding? I totally missed that. But because I don't use the web interface this bug went unnoticed. Sigh.

For the record, I changed the code to read:

if (!isxdigit(src[0])) return '\0';
if (!isxdigit(src[1])) return '\0';
c    = ctohex(src[0]) * 16 + ctohex(src[1]);

Another long time feature I've removed is email notification. I added it early on where you could submit your email address to get notified of posts, but spammers and a lack of outside interest pretty much put the kibosh on that. As I still have three users (one is me, one is Bunny, and one is one other person whom I'm not sure still reads the emails but they haven't bounced yet) I don't want to drop support completely, so now the email notifications are sent via the hook mechanism I added a few years ago.

In total, I removed over 3,000 lines of code from mod_blog. Granted, over 2,000 of them were in one function that was removed, but still, it's 3,000 lines of code I don't have to worry about any more.

Still, it's a bit scary to remove features that have been there for so long, and thus, a Halloween release.


It worked, but it failed

In posting the previous post I encounted an interesting bug!

It wasn't in mod_blog per se, but in the hook running after an entry has been added, and therein is the bug—the entry was successfully added, but the hook failed.

The hook program failed due to a compilation error that was only triggered when it ran. I took the email notification code from mod_blog and turned it into a program. I also linked to the bloging core of mod_blog to avoid having to duplicate the code to read the configuration (the email notification block is now ignored by mod_blog itself), and because the configuration format is Lua, a compiler option is needed to support Lua modules written in C—basically, -rdynamic to allow C-based Lua modules to call Lua functions (which I allow, and need, to support my particular configuration).

This is the root cause of the issue.

But in the meantime, because the hook failed to run, the script I use that uses the HTTP PUT method received a status of “500 Internal Server Error,” the entry was stored, but none of the statically generated files (index.html and the various feed files) were generated, nor email sent.

Once I figured out what happened, it was easily remedied, but that still leaves the question of what should happen? I intended the add entry post-hook to handle situations like notifications, so in this case, if the hook fails, normal processing should proceed, but how to send back that the entry post-hook failed? Looking over the HTTP status codes, perhaps I could return a “202 Accepted” when the entry post-hook fails, with some information about the failure. That could work.

Obligatory Picture

[Self-portrait with my new glasses]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

Obligatory AI Disclaimer

No AI was used in the making of this site, unless otherwise noted.

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2025 by Sean Conner. All Rights Reserved.