Hello!
Using cpio and building it with the ASAN sanitizer I have found a bug
in copyin.c. If we run cpio with the -tF flags on a file containing a
header in the old_ascii format, 59 '0' and 11 ' ' symbols, a
stack-buffer overflow error occurs in the from_ascii() function.

The problem is that the end pointer value = buf pointer + digs value
(the result of sizeof buf), so the end pointer will always
point to the next variable in the structure,
causing a stack-buffer-overflow error.

In this case, sizeof(buf) will be 11, but the end variable will point
to buf + 11 or buf[11], which does not exist because the last element
of the buf string is 10, or buf[10].

Here is the stacktrace:


=================================================================
==3718944==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x709b9740006c at pc 0x579b6ef433fa bp 0x7fff35971b40 sp 0x7fff35971b38
READ of size 1 at 0x709b9740006c thread T0
    #0 0x579b6ef433f9 in from_ascii /cpio/src/copyin.c:999:10
    #1 0x579b6ef45141 in read_in_old_ascii /cpio/src/copyin.c:1211:26
    #2 0x579b6ef44269 in read_in_header /cpio/src/copyin.c:1144:4
    #3 0x579b6ef4737a in process_copy_in /cpio/src/copyin.c:1454:7
    #4 0x579b6ef59a4c in main /cpio/src/main.c:810:3
#5 0x709b9989109a in __libc_start_main /opt/build/glibc-2.28/csu/../csu/libc-start.c:308:16 #6 0x579b6ee64709 in _start (/cpio/src/cpio+0x39709) (BuildId: 7b58717214aef0e6c8baea2fe5439ec76a0ad409)

Address 0x709b9740006c is located in stack of thread T0 at offset 108 in frame
    #0 0x579b6ef44b9f in read_in_old_ascii /cpio/src/copyin.c:1191


Steps to reproduce this error:

1. Build the project with AddressSanitizer:

export CC=clang
export CXX=clang++
export CFLAGS="-g -O0 -fsanitize=address"
export CXXFLAGS="-g -O0 -fsanitize=address"
./bootstrap
./configure --enable-mt --build x86_64-linux-gnu CFLAGS="$CFLAGS"
make

2. Create a file, that contains information, like this:

echo "07070700000000000000000000000000000000000000000000000000000000000 " > input_archive

3. Run cpio as follows:

./cpio -tF input_archive

4. You will get an ASAN report


Here is the diff, that fixes the error:

diff --git a/src/copyin.c b/src/copyin.c
index 48fb95d..6fa25f1 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -992,7 +992,7 @@ from_ascii (char const *where, size_t digs, unsigned logbase)
 {
   uintmax_t value = 0;
   char const *buf = where;
-  char const *end = buf + digs;
+  char const *end = buf + digs - 1;
   int overflow = 0;
   static char codetab[] = "0123456789ABCDEF";


Or this:

diff --git a/src/extern.h b/src/extern.h
index 5f3381a..e31f69f 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -224,7 +224,7 @@ void change_dir (void);

 uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);

-#define FROM_OCTAL(f) from_ascii (f, sizeof f, LG_8)
+#define FROM_OCTAL(f) from_ascii (f, sizeof f - 1, LG_8)
 #define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)

 void delay_cpio_set_stat (struct cpio_file_stat *file_stat,


Idk, which fix is the correct, but any of them fixes this overflow.

Reply via email to