Skip to content

Use musl implementation of gethostbyname/gethostbyaddr functions. NFC #21067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 5 additions & 51 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -1824,57 +1824,11 @@ addToLibrary({
}
},

// note: lots of leaking here!
gethostbyaddr__deps: ['$DNS', '$getHostByName', '$inetNtop4', '$setErrNo'],
gethostbyaddr__proxy: 'sync',
gethostbyaddr: (addr, addrlen, type) => {
if (type !== {{{ cDefs.AF_INET }}}) {
setErrNo({{{ cDefs.EAFNOSUPPORT }}});
// TODO: set h_errno
return null;
}
addr = {{{ makeGetValue('addr', '0', 'i32') }}}; // addr is in_addr
var host = inetNtop4(addr);
var lookup = DNS.lookup_addr(host);
if (lookup) {
host = lookup;
}
return getHostByName(host);
},

gethostbyname__deps: ['$getHostByName'],
gethostbyname__proxy: 'sync',
gethostbyname: (name) => getHostByName(UTF8ToString(name)),

$getHostByName__deps: ['malloc', '$stringToNewUTF8', '$DNS', '$inetPton4'],
$getHostByName: (name) => {
// generate hostent
var ret = _malloc({{{ C_STRUCTS.hostent.__size__ }}}); // XXX possibly leaked, as are others here
var nameBuf = stringToNewUTF8(name);
{{{ makeSetValue('ret', C_STRUCTS.hostent.h_name, 'nameBuf', POINTER_TYPE) }}};
var aliasesBuf = _malloc(4);
{{{ makeSetValue('aliasesBuf', '0', '0', POINTER_TYPE) }}};
{{{ makeSetValue('ret', C_STRUCTS.hostent.h_aliases, 'aliasesBuf', 'i8**') }}};
var afinet = {{{ cDefs.AF_INET }}};
{{{ makeSetValue('ret', C_STRUCTS.hostent.h_addrtype, 'afinet', 'i32') }}};
{{{ makeSetValue('ret', C_STRUCTS.hostent.h_length, '4', 'i32') }}};
var addrListBuf = _malloc(12);
{{{ makeSetValue('addrListBuf', '0', 'addrListBuf+8', POINTER_TYPE) }}};
{{{ makeSetValue('addrListBuf', '4', '0', POINTER_TYPE) }}};
{{{ makeSetValue('addrListBuf', '8', 'inetPton4(DNS.lookup_name(name))', 'i32') }}};
{{{ makeSetValue('ret', C_STRUCTS.hostent.h_addr_list, 'addrListBuf', 'i8**') }}};
return ret;
},

gethostbyname_r__deps: ['gethostbyname', 'memcpy', 'free'],
gethostbyname_r__proxy: 'sync',
gethostbyname_r: (name, ret, buf, buflen, out, err) => {
var data = _gethostbyname(name);
_memcpy(ret, data, {{{ C_STRUCTS.hostent.__size__ }}});
_free(data);
{{{ makeSetValue('err', '0', '0', 'i32') }}};
{{{ makeSetValue('out', '0', 'ret', '*') }}};
return 0;
_emscripten_lookup_name__deps: ['$UTF8ToString', '$DNS', '$inetPton4'],
_emscripten_lookup_name: (name) => {
// uint32_t _emscripten_lookup_name(const char *name);
var nameString = UTF8ToString(name);
return inetPton4(DNS.lookup_name(nameString));
},

getaddrinfo__deps: ['$Sockets', '$DNS', '$inetPton4', '$inetNtop4', '$inetPton6', '$inetNtop6', '$writeSockaddr', 'malloc', 'htonl'],
Expand Down
4 changes: 1 addition & 3 deletions src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ sigs = {
_emscripten_fs_load_embedded_files__sig: 'vp',
_emscripten_get_now_is_monotonic__sig: 'i',
_emscripten_get_progname__sig: 'vpi',
_emscripten_lookup_name__sig: 'ip',
_emscripten_notify_mailbox_postmessage__sig: 'vppp',
_emscripten_push_main_loop_blocker__sig: 'vppp',
_emscripten_push_uncounted_main_loop_blocker__sig: 'vppp',
Expand Down Expand Up @@ -966,9 +967,6 @@ sigs = {
filledEllipseRGBA__sig: 'ipiiiiiiii',
getaddrinfo__sig: 'ipppp',
getentropy__sig: 'ipp',
gethostbyaddr__sig: 'ppii',
gethostbyname__sig: 'pp',
gethostbyname_r__sig: 'ipppppp',
getnameinfo__sig: 'ipipipii',
getprotobyname__sig: 'pp',
getprotobynumber__sig: 'pi',
Expand Down
2 changes: 2 additions & 0 deletions system/lib/libc/emscripten_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ void __resumeException(void* exn);
void __cxa_call_unexpected(void* exn);
void llvm_eh_typeid_for(void* exn);

uint32_t _emscripten_lookup_name(const char *name);

#ifdef __cplusplus
}
#endif
34 changes: 34 additions & 0 deletions system/lib/libc/lookup_name.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Emscripten-specific version of musl/src/network/lookup_name.c

#include <assert.h>
#include <string.h>
#include "musl/src/network/lookup.h"
#include "emscripten_internal.h"

int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags)
{
/* We currently only support the callsite in gethostbyname2_r which
* passes AI_CANONNAME. Remove this assertion when if we ever expand
* this support. */
assert(flags == AI_CANONNAME);

if (family != AF_INET) {
return EAI_SYSTEM;
}

/* This hunk is a duplicated from musl/src/network/lookup_name.c */
*canon = 0;
if (name) {
/* reject empty name and check len so it fits into temp bufs */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a check for an empty name, but where is it rejected? (It looks like we continue down and send null to UTF8ToString in JS, which is fine.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we handle that case.. but also the old code didn't handle it either, so I'm temped to leave it as is. I think passing NULL to gethostbyname is most likely undefined behaviour and I suppose we don't have a test for it.

size_t l = strnlen(name, 255);
if (l-1 >= 254)
return EAI_NONAME;
memcpy(canon, name, l+1);
}

/* We only support a single address */
uint32_t addr = _emscripten_lookup_name(name);
memset(&buf[0], 0, sizeof(buf[0]));
memcpy(&buf[0].addr, &addr, sizeof(addr));
return 1;
}
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_hello_O0.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8429
8422
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_hello_O0.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23103
23089
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_minimal_O0.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7256
7251
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_minimal_O0.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19727
19713
9 changes: 5 additions & 4 deletions test/other/test_support_errno.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <emscripten/em_asm.h>
#include <emscripten/em_js.h>

EM_JS_DEPS(test, "$setErrNo");

int main() {
void* rtn = gethostbyaddr(NULL, 0, 0);
printf("rtn : %p\n", rtn);
EM_ASM(setErrNo(5));
printf("errno : %d\n", errno);
printf("strerror: %s\n", strerror(errno));
return 0;
Expand Down
1 change: 0 additions & 1 deletion test/other/test_support_errno.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
rtn : 0
errno : 5
strerror: Address family not supported by protocol
2 changes: 1 addition & 1 deletion test/other/test_support_errno_disabled.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
rtn : 0
failed to set errno from JS
errno : 0
strerror: No error information
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
58284
58265
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_strict.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
57140
57121
2 changes: 1 addition & 1 deletion test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -11918,7 +11918,7 @@ def test_default_to_cxx(self):
'minimal': (['-sMINIMAL_RUNTIME', '-sSUPPORT_ERRNO'],),
})
def test_support_errno(self, args):
self.emcc_args += args
self.emcc_args += args + ['-sEXPORTED_FUNCTIONS=_main,___errno_location']

self.do_other_test('test_support_errno.c')
size_default = os.path.getsize('test_support_errno.js')
Expand Down
7 changes: 5 additions & 2 deletions tools/system_libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
'listen.c', 'accept.c', 'getsockname.c', 'getpeername.c', 'send.c',
'recv.c', 'sendto.c', 'recvfrom.c', 'sendmsg.c', 'recvmsg.c',
'getsockopt.c', 'setsockopt.c', 'freeaddrinfo.c',
'gethostbyaddr.c', 'gethostbyaddr_r.c', 'gethostbyname.c',
'gethostbyname_r.c', 'gethostbyname2.c', 'gethostbyname2_r.c',
'in6addr_any.c', 'in6addr_loopback.c', 'accept4.c']

# Experimental: Setting EMCC_USE_NINJA will cause system libraries to get built with ninja rather
Expand Down Expand Up @@ -1064,12 +1066,12 @@ def get_files(self):
ignore += [
'memcpy.c', 'memset.c', 'memmove.c', 'getaddrinfo.c', 'getnameinfo.c',
'res_query.c', 'res_querydomain.c',
'proto.c', 'gethostbyaddr.c', 'gethostbyaddr_r.c', 'gethostbyname.c',
'gethostbyname2_r.c', 'gethostbyname_r.c', 'gethostbyname2.c',
'proto.c',
'syscall.c', 'popen.c', 'pclose.c',
'getgrouplist.c', 'initgroups.c', 'wordexp.c', 'timer_create.c',
'getentropy.c',
'getauxval.c',
'lookup_name.c',
# 'process' exclusion
'fork.c', 'vfork.c', 'posix_spawn.c', 'posix_spawnp.c', 'execve.c', 'waitid.c', 'system.c',
'_Fork.c',
Expand Down Expand Up @@ -1258,6 +1260,7 @@ def get_files(self):
'mktime.c',
'tzset.c',
'kill.c',
'lookup_name.c',
'pthread_sigmask.c',
'raise.c',
'sigaction.c',
Expand Down