diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2011-09-23 15:38:36 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2011-10-05 13:45:16 -0700 |
commit | d4e85a1afe0a3310a3c8336c2824775901cc27d7 (patch) | |
tree | caf44e689fec5d36aef2439c8016bbebee413148 | |
parent | 3793ac56b4c4f9bf0bddc306a0cec21118683728 (diff) | |
download | git-d4e85a1afe0a3310a3c8336c2824775901cc27d7.tar.gz |
get_sha1_hex(): do not read past a NUL character
Previously, get_sha1_hex() would read one character past the end of a
null-terminated string whose strlen was an even number less than 40.
Although the function correctly returned -1 in these cases, the extra
memory access might have been to uninitialized (or even, conceivably,
unallocated) memory.
Add a check to avoid reading past the end of a string.
This problem was discovered by Thomas Rast <trast@student.ethz.ch>
using valgrind.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | cache.h | 9 | ||||
-rw-r--r-- | hex.c | 10 |
2 files changed, 18 insertions, 1 deletions
@@ -819,7 +819,16 @@ static inline int get_sha1_with_context(const char *str, unsigned char *sha1, st { return get_sha1_with_context_1(str, sha1, orc, 0, NULL); } + +/* + * Try to read a SHA1 in hexadecimal format from the 40 characters + * starting at hex. Write the 20-byte result to sha1 in binary form. + * Return 0 on success. Reading stops if a NUL is encountered in the + * input, so it is safe to pass this function an arbitrary + * null-terminated string. + */ extern int get_sha1_hex(const char *hex, unsigned char *sha1); + extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ extern int read_ref(const char *filename, unsigned char *sha1); extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *); @@ -39,7 +39,15 @@ int get_sha1_hex(const char *hex, unsigned char *sha1) { int i; for (i = 0; i < 20; i++) { - unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]); + unsigned int val; + /* + * hex[1]=='\0' is caught when val is checked below, + * but if hex[0] is NUL we have to avoid reading + * past the end of the string: + */ + if (!hex[0]) + return -1; + val = (hexval(hex[0]) << 4) | hexval(hex[1]); if (val & ~0xff) return -1; *sha1++ = val; |