GDBM_File is meant to croak() if the gdbm library has a fatal error.
authorNicholas Clark <nick@ccl4.org>
Thu, 13 Dec 2012 15:38:17 +0000 (16:38 +0100)
committerNicholas Clark <nick@ccl4.org>
Thu, 13 Dec 2012 15:38:17 +0000 (16:38 +0100)
commitceab7011c2af9d86bd7743d6c1b7c37540fe14f1
treed74abdd79993991ee8bd96c0c5fd614162666312
parent71446f2da4f4887cb6b60b4ddee4754faee70d3d
GDBM_File is meant to croak() if the gdbm library has a fatal error.

gdbm_open() takes a fifth argument, for an optional callback function used
to report a fatal error. Since it was added in 5.000, the tied hash wrapper
implemented in GDBM_File.xs has (intended) to default this to croak().
However, the callback expects a function taking a single const char *
argument, whereas croak(const char *pat, ...) has variable arguments.
The code as-was had two bugs

1) The calling ABI on some platforms differs between a (known) variable-
   argument function, and one which takes (known) fixed arguments. As the
   call site knows the pointer is to a function with fixed arguments, the
   calling convention it uses doesn't match what Perl_croak_nocontext()
   expects, which can lead to crashes.
2) A message containing % characters will be interpreted as a printf format.

Both these are fixed by using a small station function as a wrapper, which
takes a single string argument, and passes to croak() a "%s" format string,
followed by the string for the error message.

Add a test for this functionality.
MANIFEST
ext/GDBM_File/GDBM_File.pm
ext/GDBM_File/GDBM_File.xs
ext/GDBM_File/t/fatal.t [new file with mode: 0644]