[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
%.1s format with vasnprintf reads more than one byte from argument
From: |
Ben Pfaff |
Subject: |
%.1s format with vasnprintf reads more than one byte from argument |
Date: |
Sun, 22 Feb 2009 22:10:56 -0800 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.2 (gnu/linux) |
C89 and C99 are pretty clear that specifying a precision on a %s
directive to printf prevents reading more than that many bytes
from the argument and that in that case no null terminator is
required:
s If no l length modifier is present, the argument shall be
a pointer to the initial element of an array of character
type.237) Characters from the array are written up to (but
not including) the terminating null character. If the
precision is specified, no more than that many bytes are
written. If the precision is not specified or is greater
than the size of the array, the array shall contain a null
character.
But running valgrind on test-vasnprintf when USE_SNPRINTF is not
selected, when the appended patch to test-vasnprintf.c is
applied, makes it clear that vasnprintf() will read beyond the
specified precision:
==3968== Conditional jump or move depends on uninitialised value(s)
==3968== at 0x40239D7: strlen (mc_replace_strmem.c:242)
==3968== by 0x8049065: vasnprintf (vasnprintf.c:4044)
==3968== by 0x8048655: my_asnprintf (test-vasnprintf.c:47)
==3968== by 0x80488F6: main (test-vasnprintf.c:131)
The culprit is pretty clearly this code in lib/vasnprintf.c:
case 's':
[...]
tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
break;
The obvious solution would be to use strnlen in place of strlen
here, but I don't know whether you would object to the additional
dependency. Maybe you want to introduce a "local_strnlen"
function instead.
Something similar would be needed for the wide-character case
(presumably a "local_wcsnlen").
diff --git a/tests/test-vasnprintf.c b/tests/test-vasnprintf.c
index 2f3f890..50c6956 100644
--- a/tests/test-vasnprintf.c
+++ b/tests/test-vasnprintf.c
@@ -119,10 +119,24 @@ test_asnprintf ()
}
}
+static void
+test_precision (void)
+{
+ size_t length = 0;
+ char *p, *s;
+
+ p = malloc (2);
+ ASSERT (p != NULL);
+ *p = 'x';
+ s = my_asnprintf (NULL, &length, "%.1s", p);
+ ASSERT (!strcmp (s, "x"));
+}
+
int
main (int argc, char *argv[])
{
test_vasnprintf ();
test_asnprintf ();
+ test_precision ();
return 0;
}
--
Ben Pfaff
http://benpfaff.org
- %.1s format with vasnprintf reads more than one byte from argument,
Ben Pfaff <=