From: alice Date: Sat, 15 Jun 2024 00:26:14 +0000 (+0200) Subject: rar: fix UB negation overflow for INT32_MIN address (#2235) X-Git-Tag: v3.7.5~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d12cb9ab217a0b30c7ddc33d7ebad44fa22f7d5e;p=thirdparty%2Flibarchive.git rar: fix UB negation overflow for INT32_MIN address (#2235) certain rar files seem to have the lowest possible address here, so flip the argument order to correctly evaluate this instead of invoking UB (caught via sanitize=undefined) --- the backtrace looks something like: ``` * frame #0: 0x00007a1e3898727b libarchive.so.13`execute_filter [inlined] execute_filter_e8(filter=, vm=, pos=, e9also=) at archive_read_support_format_rar.c:3640:47 frame #1: 0x00007a1e3898727b libarchive.so.13`execute_filter(a=, filter=0x00007a1e39e2f090, vm=0x00007a1e31b1efd0, pos=) at archive_read_support_format_rar.c:0 frame #2: 0x00007a1e38983ac3 libarchive.so.13`read_data_compressed [inlined] run_filters(a=0x00007a1e34209700) at archive_read_support_format_rar.c:3395:8 frame #3: 0x00007a1e38983a9e libarchive.so.13`read_data_compressed(a=0x00007a1e34209700, buff=0x00007a1e31a01fd8, size=0x00007a1e31a01fd0, offset=0x00007a1e31a01fc0, looper=1) at archive_read_support_format_rar.c:2083:12 frame #4: 0x00007a1e38981b10 libarchive.so.13`archive_read_format_rar_read_data(a=0x00007a1e34209700, buff=0x00007a1e31a01fd8, size=0x00007a1e31a01fd0, offset=0x00007a1e31a01fc0) at archive_read_support_format_rar.c:1130:11 frame #5: 0x00006158bc5d30d3 file-roller`extract_archive_thread(result=0x00007a1e3711e2b0, object=, cancellable=0x00007a1e3870bf20) at fr-archive-libarchive.c:999:17 frame #6: 0x00007a1e39928d6d libgio-2.0.so.0`run_in_thread(job=, c=, _data=0x00007a1e326e9740) at gsimpleasyncresult.c:899:5 frame #7: 0x00007a1e3990614e libgio-2.0.so.0`io_job_thread(task=, source_object=, task_data=0x00007a1e2307fc20, cancellable=) at gioscheduler.c:75:16 frame #8: 0x00007a1e399433bf libgio-2.0.so.0`g_task_thread_pool_thread(thread_data=0x00007a1e35c18ab0, pool_data=) at gtask.c:1583:3 frame #9: 0x00007a1e39db77e8 libglib-2.0.so.0`g_thread_pool_thread_proxy(data=) at gthreadpool.c:336:15 frame #10: 0x00007a1e39db5bfb libglib-2.0.so.0`g_thread_proxy(data=0x00007a1e378147d0) at gthread.c:835:20 frame #11: 0x00007a1e3a0b5c7b ld-musl-x86_64.so.1`start(p=0x00007a1e31a02170) at pthread_create.c:208:17 frame #12: 0x00007a1e3a0b8a8b ld-musl-x86_64.so.1`__clone + 47 ``` note the 0xd which is 14 which is NegateOverflow in ubsan: ``` (lldb) x/1i $pc -> 0x7a1e3898727b: 67 0f b9 40 0d other ud1l 0xd(%eax), %eax ``` for reference, the totally legal rar file is https://img.ayaya.dev/05WYGFOcRPN9 , and this seems to only crash when extracted via file-roller (or inside nautilus) --- diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 157836b42..93d738a5c 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -3681,7 +3681,7 @@ execute_filter_e8(struct rar_filter *filter, struct rar_virtual_machine *vm, siz { uint32_t currpos = (uint32_t)pos + i + 1; int32_t address = (int32_t)vm_read_32(vm, i + 1); - if (address < 0 && currpos >= (uint32_t)-address) + if (address < 0 && currpos >= -(uint32_t)address) vm_write_32(vm, i + 1, address + filesize); else if (address >= 0 && (uint32_t)address < filesize) vm_write_32(vm, i + 1, address - currpos);