summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2012-10-23 16:10:21 +0200
committerJim Meyering <jim@meyering.net>2012-10-23 16:13:40 +0200
commit36a93b370040444d6d2240100404490064b6fa00 (patch)
tree32ff82b393ebbe6fb3d64de0c94ecdef89abe86b
parentb7ac27d5fe9ef7751b79812dc0095a59bddbfd4d (diff)
downloadidutils-36a93b370040444d6d2240100404490064b6fa00.tar.gz
idutils-36a93b370040444d6d2240100404490064b6fa00.tar.bz2
idutils-36a93b370040444d6d2240100404490064b6fa00.zip
lid: avoid reading beyond end of buffer for a long name
* libidu/idfile.h (stzncpy): Define, from coreutils. * src/lid.c (query_ambiguous_prefix): Avoid buffer overrun. Using strncpy to copy a too-long name would result in a "name" that is not NUL-terminated, yet that name would be treated as a NUL-terminated string immediately afterwards, via report_func, which attempts to print it. * libidu/fnprint.c (root_name): Use stzncpy in place of strncpy. * NEWS (Bug fixes): Mention the bug fix.
-rw-r--r--NEWS4
-rw-r--r--libidu/fnprint.c6
-rw-r--r--libidu/idfile.h15
-rw-r--r--src/lid.c4
4 files changed, 22 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 56ba539..824d037 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ GNU idutils NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
+** Bug fixes
+
+ lid is no longer susceptible to a buffer overrun
+
* Noteworthy changes in release 4.6 (2012-02-03) [stable]
diff --git a/libidu/fnprint.c b/libidu/fnprint.c
index b8d97ce..4129441 100644
--- a/libidu/fnprint.c
+++ b/libidu/fnprint.c
@@ -46,11 +46,7 @@ root_name (char const *file_name)
char const *dot = strrchr (file_name, '.');
if (dot)
- {
- int length = dot - file_name;
- strncpy (file_name_buffer, file_name, length);
- file_name_buffer[length] = '\0';
- }
+ stzncpy (file_name_buffer, file_name, dot - file_name);
else
strcpy (file_name_buffer, file_name);
return file_name_buffer;
diff --git a/libidu/idfile.h b/libidu/idfile.h
index 739819d..3775d7a 100644
--- a/libidu/idfile.h
+++ b/libidu/idfile.h
@@ -225,4 +225,19 @@ extern off_t largest_member_file;
#define DEFAULT_ID_FILE_NAME "ID"
+/* Like stpncpy, but do ensure that the result is NUL-terminated,
+ and do not NUL-pad out to LEN. I.e., when strnlen (src, len) == len,
+ this function writes a NUL byte into dest[len]. Thus, the length
+ of the destination buffer must be at least LEN + 1.
+ The DEST and SRC buffers must not overlap. */
+static inline char *
+stzncpy (char *restrict dest, char const *restrict src, size_t len)
+{
+ char const *src_end = src + len;
+ while (src < src_end && *src)
+ *dest++ = *src++;
+ *dest = 0;
+ return dest;
+}
+
#endif /* not _idfile_h_ */
diff --git a/src/lid.c b/src/lid.c
index cd307c0..8a31268 100644
--- a/src/lid.c
+++ b/src/lid.c
@@ -1042,7 +1042,7 @@ query_ambiguous_prefix (unsigned int limit, report_func_t report_func)
{
if (consecutive && key_style != ks_token)
{
- strncpy (&name[1], old, limit);
+ stzncpy (&name[1], old, limit - 2);
(*report_func) (name, bits_to_flinkv (bits_vec));
}
consecutive = 0;
@@ -1064,7 +1064,7 @@ query_ambiguous_prefix (unsigned int limit, report_func_t report_func)
}
if (consecutive && key_style != ks_token)
{
- strncpy (&name[1], new, limit);
+ stzncpy (&name[1], new, limit - 2);
(*report_func) (name, bits_to_flinkv (bits_vec));
}
return count;