From a0e1c71a7c117ad021f30b3bd66c320e13246667 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Mon, 17 Mar 2025 07:13:54 +0100 Subject: [PATCH 1/4] Include arpa/inet.h instead of sys/endian.h The header is included to get defintion for htons. In termux the definition is in sys/endian.h, but on other systems it is in arpa/inet.h. arpa/inet.h includes sys/endian.h though, so including that header works in termux as well. Change to arpa/inet.h so that termux-api-package can be easily compiled both in termux and for other systems. --- termux-api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/termux-api.c b/termux-api.c index 3cfda8b..ddc157b 100644 --- a/termux-api.c +++ b/termux-api.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include From 530f292a8e77e6dc2255b42fbe48f1ced319a485 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Wed, 26 Mar 2025 16:49:19 +0100 Subject: [PATCH 2/4] termux-api: free malloc'ed child_argv array on execv error We exit right after so this is not exactly strictly necessary, but that might change at some point and is good practise in any case. --- termux-api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/termux-api.c b/termux-api.c index ddc157b..30b848b 100644 --- a/termux-api.c +++ b/termux-api.c @@ -275,6 +275,8 @@ _Noreturn void exec_am_broadcast(int argc, char** argv, // Use an a executable taking care of PATH and LD_LIBRARY_PATH: execv(PREFIX "/bin/am", child_argv); + // We should not reach here, if we do, then free memory we malloc'ed + free(child_argv); perror("execv(\"" PREFIX "/bin/am\")"); exit(1); } From 512a252ba6220d5a6c9af4b96cb4e5153740c8aa Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Wed, 26 Mar 2025 16:51:36 +0100 Subject: [PATCH 3/4] termux-api: handle malloc errors malloc might fail to allocate memory for child_argv. Ensure it was successfully allocated before trying to set its elements. --- termux-api.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/termux-api.c b/termux-api.c index 30b848b..5c86329 100644 --- a/termux-api.c +++ b/termux-api.c @@ -248,6 +248,10 @@ _Noreturn void exec_am_broadcast(int argc, char** argv, int const extra_args = 15; // Including ending NULL. char** child_argv = malloc((sizeof(char*)) * (argc + extra_args)); + if (child_argv == NULL) { + perror("malloc failed for am child args"); + exit(1); + } child_argv[0] = "am"; child_argv[1] = "broadcast"; From 0edd4d450710e399c1e3e4f44558eecc0f78a068 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Wed, 26 Mar 2025 16:58:54 +0100 Subject: [PATCH 4/4] Fixed: only malloc as many bytes as are actully needed And make malloc&memcpy handling clearer. Before we potentially had an element with uninitialised memory, see discussion in termux/termux-api-package#203. Fixes: 1ec1334b54e0 ("Initial push") --- termux-api.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/termux-api.c b/termux-api.c index 5c86329..bee5433 100644 --- a/termux-api.c +++ b/termux-api.c @@ -246,13 +246,20 @@ _Noreturn void exec_am_broadcast(int argc, char** argv, // Close stdin: close(STDIN_FILENO); - int const extra_args = 15; // Including ending NULL. - char** child_argv = malloc((sizeof(char*)) * (argc + extra_args)); - if (child_argv == NULL) { + const int child_pre_argc = 14; + const int child_post_argc = argc - 1; // Except `argv[0]`. + const int child_argc = child_pre_argc + child_post_argc; + + size_t child_argv_size = (sizeof(char*)) * (child_argc + 1); // Including trailing `NULL`. + // Do not directly cast, otherwise can trigger null pointer dereference if `NULL` is returned. + void* result = malloc(child_argv_size); + if (result == NULL) { perror("malloc failed for am child args"); exit(1); } + char **child_argv = (char **) result; + child_argv[0] = "am"; child_argv[1] = "broadcast"; child_argv[2] = "--user"; @@ -268,13 +275,12 @@ _Noreturn void exec_am_broadcast(int argc, char** argv, child_argv[11] = input_address_string; child_argv[12] = "--es"; child_argv[13] = "api_method"; - child_argv[14] = argv[1]; - // Copy the remaining arguments -2 for first binary and second api name: - memcpy(child_argv + extra_args, argv + 2, (argc-1) * sizeof(char*)); + // Copy the remaining arguments except `argv[0]`, `argv[1]` should be `api_method` extra value: + memcpy(child_argv + child_pre_argc, argv + 1, child_post_argc * sizeof(char*)); // End with NULL: - child_argv[argc + extra_args - 1] = NULL; + child_argv[child_argc] = NULL; // Use an a executable taking care of PATH and LD_LIBRARY_PATH: execv(PREFIX "/bin/am", child_argv);