[Nut-upsdev] valgrind and libusb calls

Charles Lepple
Mon, 20 Nov 2006 03:27:57 -0000

NUT developers,

just thought I'd share some notes and ideas on using valgrind against
the NUT USB drivers on Linux.

Stepping back a bit, I wanted to make sure that the tripplite_usb
driver* wasn't using any uninitialized memory, or leaking memory over
time. valgrind (specifically, the memcheck tool) runs the code in a
special dynamic translator that checks every memory access to see if
the address is valid, and if so, if the addressed memory has been
initialized.

* And other drivers as well, but I figured I'd "clean my own
house" first.

The problem is that the buffers returned from libusb are all being
marked as invalid (the bytes themselves, not the address).

I see at least two solutions to this:

1) Clear all buffers to zero before calling libusb functions that
write to a buffer (usb_get_interrupt, usb_get_string*,
usb_control_msg, etc.)

2) Mark the valid portions of the buffer after the libusb call with
VALGRIND_MAKE_READABLE.

The big advantage of the first method is that it keeps the code
looking clean, and means we don't have to do any conditional inclusion
of valgrind's memcheck.h or anything. The main drawback is that it
doesn't catch cases where we get a short read, and code reads past the
end of the valid buffer (because we have marked it all as valid before
the libusb call).

The second option is slightly more intrusive because you need a bunch
of VALGRIND_MAKE_READABLE calls, and you have to either include a few
valgrind headers with the distribution (BSD-licensed), or
conditionally include them and provide stubs for when valgrind is not
installed.

In the second case, the valgrind macro inserts a handful of opcodes
into the program which leave the registers and flags unchanged, but
are recognized as a magic sequence when run under valgrind. Of course,
as a macro, it can be disabled entirely.

Any thoughts on this?

--
- Charles Lepple