This describes a typical sequence of events when I notice a bug on my system, which demonstrates the fabulous tools available today to stream-line the process.

So today I noticed that the bc calculator command, no longer works correctly on my system. Very quickly I established that functions weren't outputting anything:

$ echo 'e(1)' | bc -l | wc -c
0
Now the bc version I had on Fedora 11 worked fine, as did another Fedora 14 system I had access to. So there was something particular to the Fedora 14 version on my system that broke it. I also verified the binary was OK with rpm -qV bc. So next step is to get the source:
yum-builddep bc
rpmbuild -bp ~/rpmbuild/SPECS/bc.spec
cd ~/rpmbuild/BUILD/bc-*/
CFLAGS=-ggdb ./configure --quiet
make
Now to check the rebuilt version
$ echo "e(1)" | bc/bc -l # still broken
Let's vary things a little to see if it's something to do with output
$ echo "v=e(1)" | bc/bc -l
(standard_in) 2: Assignment of a void expression
Hmm, so it thinks e() is a void function, which suggests an issue internal to bc, but only on my system. Thinking cap on ... and ... aha!, I remember that I proactively trigger uninitialized heap memory bugs by setting the following in my .bashrc:
export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
And sure enough, it works when I disable that:
echo "e(1)" | MALLOC_PERTURB_= bc/bc -l
2.71828182845904523536
So how to find this bug. Well traditionally I would have looked at the code around handling of the "void" flag on the heap in bc, and probably would have resorted to a debugger to help. But these days we have the magical valgrind to help. Let's see if it notices anything...
$ echo "e(1)" | valgrind bc/bc -l
==19142== Memcheck, a memory error detector
==19142== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==19142== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==19142== Command: bc/bc -l
==19142==
==19142== Conditional jump or move depends on uninitialised value(s)
==19142==    at 0x804A95E: yyparse (bc.y:657)
==19142==    by 0x8048F2A: main (main.c:259)
Whoa! That was easy. As usual valgrind never ceases to amaze. Indeed the above states that f_void is being accessed uninitialized. So a quick look at the code resulted in an obvious fix. Let's see how to best supply this fix upstream. This is where things get a little non standard. A good place to start is to open the web page for the package using the following commands for rpm and deb based systems.
xdg-open $(rpm -q --qf='%{URL}' bc)
xdg-open $(dpkg-query -W --showformat='${Homepage}' bc)
Also one often gets useful contact info in the BUGS section of the command's man page. So reading the above suggests that this project is a bit antiquated and doesn't have a great openness score. In any case, we already have the latest source, so we must now send the following diff directly to the author. We'll also send the patch to my distro so others can get it in a more timely fashion.
$ diff storage.c.orig storage.c
--- storage.c.orig      2010-12-21 19:43:14.663540110 +0000
+++ storage.c   2010-12-21 19:42:01.392540111 +0000
@@ -99,6 +99,7 @@
    {
       f = &functions[indx];
       f->f_defined = FALSE;
+      f->f_void = FALSE;
       f->f_body = (char *) bc_malloc (BC_START_SIZE);
       f->f_body_size = BC_START_SIZE;
       f->f_code_size = 0;
[Update: I was pleasantly surprised to see gentoo fixed within hours of writing this, and that in turn prompted me to report to debian also, given the issues with fixes comming from upstream for this project.

Note also, one should not blindly initialize memory for performance reasons.]

© Dec 22 2010