apk3 segfault when a package gets replaced with the same name
how to reproduce:
i made myself a pair of dummy packages with random contents, like this:
$ mkdir -p inpfiles/usr/lib
$ touch inpfiles/usr/lib/test.txt
$ mkdir -p inpfiles/usr/bin
$ touch inpfiles/usr/bin/test
$ mkdir -p inpfiles/usr/share/test
$ touch inpfiles/usr/share/test/bla.txt
$ ln -s test.txt inpfiles/usr/lib/test.txt.2
$ apk mkpkg --info name:test --info version:0.1-r0 --files inpfiles
$ apk mkpkg --info name:test-git --info version:0.2-r0 --info provides:test=0.2-r0 --files inpfiles
then made a repo:
$ mkdir -p repo/x86_64
$ mv *.apk repo/x86_64
$ cd repo/x86_64
$ apk mkndx --allow-untrusted --output APKINDEX.tar.gz *.apk
the dump looks like so:
#%SCHEMA: 78646E69
# ADB block, size: 268, compat: 0, ver: 0
packages: # 2 items
- name: test
version: 0.1-r0
unique-id: 81c897558f2334a71fa0397ef3cec0611f6bf263
arch: x86_64
installed-size: 4096 B
file-size: 393 B
- name: test-git
version: 0.2-r0
unique-id: 8cbbec5d1bf06043ccf4dbe25714b44d38939b15
arch: x86_64
installed-size: 4096 B
file-size: 403 B
provides: # 1 items
- test=0.2-r0
install test:
$ apk --usermode --initdb --root testroot --allow-untrusted --repository repo add test
The following NEW packages will be installed:
test-git
After this operation, 4096 B of additional disk space will be used.
Do you want to continue [Y/n]? y
(1/1) Installing test-git (0.2-r0)
OK: 0 MiB in 1 packages
trigger segfault:
$ ./src/apk --root testroot --allow-untrusted --repository repo add '!test-git'
The following packages will be REMOVED:
test-git
The following NEW packages will be installed:
test
After this operation, 0 B of additional disk space will be used.
Do you want to continue [Y/n]? y
(1/2) Purging test-git (0.2-r0)
(2/2) Installing test (0.1-r0)
zsh: segmentation fault ./src/apk --root testroot --allow-untrusted --repository repo add '!test-git'
backtrace:
* thread #1, name = 'apk', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0xdeadbef7)
frame #0: 0x00007ffff7fcb0c1 libapk.so.2`apk_db_install_directory_entry [inlined] __list_add(new=0x00007fffeeb01b90, prev=0x00007fffeed01fb0, next=0x00000000deadbeef) at apk_defines.h:344:13
341 struct list_head *prev,
342 struct list_head *next)
343 {
-> 344 next->prev = new;
345 new->next = next;
346 new->prev = prev;
347 prev->next = new;
(lldb) bt
error: libapk.so.2 0x000000000000d679: DW_TAG_variable has an invalid location: DW_OP_breg12 +0, DW_OP_convert 0x2b, DW_OP_convert 0x30, DW_OP_plus_uconst 0x1, DW_OP_stack_value
* thread #1, name = 'apk', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0xdeadbef7)
* frame #0: 0x00007ffff7fcb0c1 libapk.so.2`apk_db_install_directory_entry [inlined] __list_add(new=0x00007fffeeb01b90, prev=0x00007fffeed01fb0, next=0x00000000deadbeef) at apk_defines.h:344:13
frame #1: 0x00007ffff7fcb0c1 libapk.so.2`apk_db_install_directory_entry [inlined] list_add(new=0x00007fffeeb01b90, head=0x00007fffeed01fb0) at apk_defines.h:352:2
frame #2: 0x00007ffff7fcb0bd libapk.so.2`apk_db_install_directory_entry [inlined] apk_db_diri_new(db=0x00005555555d09e8, pkg=0x00007fffedf025b0, name=(len = 3, ptr = 0x0000000000000000), after=0x00007fffffffd730) at database.c:419:3
frame #3: 0x00007ffff7fcb08e libapk.so.2`apk_db_install_directory_entry(ctx=0x00007fffffffd688, dir=(len = 3, ptr = 0x0000000000000000)) at database.c:2529:21
frame #4: 0x00007ffff7fca9ae libapk.so.2`apk_db_install_file(ectx=0x00007fffffffd6d8, ae=0x00007fffffffb298, is=0x0000000000000000) at database.c:2787:21
frame #5: 0x00007ffff7fcc31c libapk.so.2`apk_extract_v3_next_file [inlined] apk_extract_v3_directory(ectx=0x00007fffffffd6d8) at extract_v3.c:129:6
frame #6: 0x00007ffff7fcc267 libapk.so.2`apk_extract_v3_next_file(ectx=0x00007fffffffd6d8) at extract_v3.c:165:8
frame #7: 0x00007ffff7fcbf9b libapk.so.2`apk_extract_v3(ectx=0x00007fffffffd6d8, is=0x00007fffef316fc0) at extract_v3.c:259:8
frame #8: 0x00007ffff7fcc51a libapk.so.2`apk_extract(ectx=<unavailable>, is=<unavailable>) at extract_v3.c:293:41 [artificial]
frame #9: 0x00007ffff7fc8301 libapk.so.2`apk_db_install_pkg [inlined] apk_db_unpack_pkg(db=0x00005555555d09e8, ipkg=0x00007fffedf01970, upgrade=<unavailable>, cb=(libapk.so.2`progress_cb at commit.c:128:37), cb_ctx=0x00007fffffffd7e0, script_args=0x00007fffffffc580) at database.c:3029:6
frame #10: 0x00007ffff7fc81c3 libapk.so.2`apk_db_install_pkg(db=0x00005555555d09e8, oldpkg=0x0000000000000000, newpkg=0x00007fffedf025b0, cb=(libapk.so.2`progress_cb at commit.c:128:37), cb_ctx=0x00007fffffffd7e0) at database.c:3080:7
frame #11: 0x00007ffff7fbfdd0 libapk.so.2`apk_solver_commit_changeset(db=0x00005555555d09e8, changeset=0x00007fffffffd8a0, world=0x00007fffeeb01e60) at commit.c:376:9
frame #12: 0x00007ffff7fc1047 libapk.so.2`apk_solver_commit(db=0x00005555555d09e8, solver_flags=0, world=0x00007fffeeb01e60) at commit.c:834:7
frame #13: 0x000055555555ff0d apk`add_main(ctx=0x00007fffeec03b70, ac=<unavailable>, args=0x00007fffeec041f0) at app_add.c:209:6
frame #14: 0x000055555555f361 apk`main(argc=1, argv=0x00007fffffffe660) at apk.c:604:6
frame #15: 0x00007fffefa57c2a libc.so`libc_start_main_stage2(main=(apk`main at apk.c:481), argc=<unavailable>, argv=0x00007fffffffe618) at __libc_start_main.c:95:7
frame #16: 0x000055555555e7b6 apk`_start + 22
the issue seems to trigger when ctx->diri_node
in apk_db_install_directory_entry
is NULL
; in this case, in apk_db_diri_new
, the dir->diris.next
is 0xdeadbeef
. The segfault happens when dereferencing dir->diris.next
.