`HOST_ENTRY.h_aliases` sometimes gets overwritten when returning from `gethostent`
When I run the netdb
test on my local machine I always get a SIGSEGV
when gethostbyname
is called for 'redox-os.org':
program received signal SIGSEGV, Segmentation fault.
0x0000555555651ae8 in strncasecmp (first=0x20 <error: Cannot access memory at address 0x20>, second=0x5555556831bb "redox-os.org", n=18446744073709551615) at src/header/strings/mod.rs:79
79 while *first & !32 == *second & !32 {
(gdb) bt
#0 0x0000555555651ae8 in strncasecmp (first=0x20 <error: Cannot access memory at address 0x20>, second=0x5555556831bb "redox-os.org", n=18446744073709551615) at src/header/strings/mod.rs:79
#1 0x0000555555651ac0 in strcasecmp (first=0x20 <error: Cannot access memory at address 0x20>, second=0x5555556831bb "redox-os.org") at src/header/strings/mod.rs:70
#2 0x0000555555575b5d in gethostbyname (name=0x5555556831bb "redox-os.org") at src/header/netdb/mod.rs:533
#3 0x0000555555566661 in test_hosts () at netdb.c:166
#4 0x00005555555667a6 in do_test () at netdb.c:217
#5 0x00005555555667ff in main () at netdb.c:229
The problem is that the HOST_ENTRY.h_aliases
vector contains an invalid memory reference. The values are all read correctly from my hosts file (I only have one entry and that one does not contain any aliases), so I watched with GDB where the value is changed and got this:
Breakpoint 2, gethostent () at src/header/netdb/mod.rs:652
652 if HOST_STAYOPEN == 0 {
(gdb) p host_aliases
$1 = Vec<*mut i8>(len: 2, cap: 2) = {0x0, 0x0}
(gdb) p &host_aliases
$2 = (alloc::vec::Vec<*mut i8> *) 0x7fffffffd4e0
(gdb) p HOST_ENTRY.h_aliases
$3 = (i8 **) 0x5555556c4fa0
(gdb) p *HOST_ENTRY.h_aliases
$4 = (i8 *) 0x0
(gdb) watch *HOST_ENTRY.h_aliases
Hardware watchpoint 3: *HOST_ENTRY.h_aliases
(gdb) c
Continuing.
Hardware watchpoint 3: *HOST_ENTRY.h_aliases
Old value = (i8 *) 0x0
New value = (i8 *) 0x5555556c1808 <_gm_+200> "\370\027lUUU"
0x00005555555b05a4 in dlfree (mem=0x5555556c4fa0) at src/c/dlmalloc.c:4794
4794 insert_small_chunk(fm, p, psize);
(gdb) bt
#0 0x00005555555b05a4 in dlfree (mem=0x5555556c4fa0) at src/c/dlmalloc.c:4794
#1 0x000055555558673e in c::platform::allocator::free (ptr=0x5555556c4fa0) at src/platform/allocator/dlmalloc.rs:37
#2 0x0000555555586692 in <c::platform::allocator::Allocator as core::alloc::GlobalAlloc>::dealloc (self=0x55555569c86b, ptr=0x5555556c4fa0 "\b\030lUUU", _layout=Layout = {...})
at src/platform/allocator/dlmalloc.rs:20
#3 0x0000555555682774 in __rg_dealloc (arg0=0x5555556c4fa0 "\b\030lUUU", arg1=16, arg2=8) at src/lib.rs:50
#4 0x000055555562cab2 in alloc::alloc::dealloc (ptr=0x5555556c4fa0 "\b\030lUUU", layout=Layout = {...}) at /checkout/src/liballoc/alloc.rs:80
#5 0x000055555562c8a9 in <alloc::alloc::Global as core::alloc::Alloc>::dealloc (self=0x7fffffffd4e0, ptr=NonNull<u8> = {...}, layout=Layout = {...}) at /checkout/src/liballoc/alloc.rs:128
#6 0x000055555564bad8 in <alloc::raw_vec::RawVec<T, A>>::dealloc_buffer (self=0x7fffffffd4e0) at /checkout/src/liballoc/raw_vec.rs:713
#7 0x000055555564eece in <alloc::raw_vec::RawVec<T, A> as core::ops::drop::Drop>::drop (self=0x7fffffffd4e0) at /checkout/src/liballoc/raw_vec.rs:722
#8 0x0000555555634bce in core::ptr::drop_in_place () at /checkout/src/libcore/ptr.rs:59
#9 0x0000555555634f4e in core::ptr::drop_in_place () at /checkout/src/libcore/ptr.rs:59
#10 0x0000555555576ba3 in gethostent () at src/header/netdb/mod.rs:656
#11 0x0000555555575a22 in gethostbyname (name=0x5555556831bb "redox-os.org") at src/header/netdb/mod.rs:518
#12 0x0000555555566661 in test_hosts () at netdb.c:166
#13 0x00005555555667a6 in do_test () at netdb.c:217
#14 0x00005555555667ff in main () at netdb.c:229
I included some additional commands to hopefully make clear what the different addresses point to.
The value *HOST_ENTRY.h_aliases
is set to is always the same. And since the issue only occurs when calling gethostbyname
with 'redox-os.org' and not for any of the calls before that, I assume that value plays a role.
I played around with the content of the hosts file and this seems to be about the 'simplest':
111.111.111.111 example.com
There is a newline at the end of the file. The value written to *HOST_ENTRY.h_aliases
is always the same and does not directly depend on the contents of the host file.
All my tests were done with the newest master commit as of this writing (ID: 116cbda8).