1
0
Fork 0
forked from fun/fun

Some small injection fixes. (0.42.2)

This commit is contained in:
Johannes Findeisen 2026-06-14 22:09:49 +02:00
commit 1b90493a7a
4 changed files with 42 additions and 7 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(fun VERSION 0.42.1 LANGUAGES C) project(fun VERSION 0.42.2 LANGUAGES C)
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)

View file

@ -142,11 +142,26 @@ int main(int argc, char **argv) {
} }
char *joined = (char *)malloc(total); char *joined = (char *)malloc(total);
if (joined) { if (joined) {
joined[0] = '\0'; size_t off = 0;
for (int i = 0; i < sargc; ++i) { for (int i = 0; i < sargc; ++i) {
strcat(joined, argv[sargi + i]); int written = snprintf(joined + off, (off < total ? total - off : 0),
if (i + 1 < sargc) strcat(joined, " "); "%s%s",
argv[sargi + i],
(i + 1 < sargc) ? " " : "");
if (written < 0) { /* encoding error */
off = total; /* force stop */
break;
}
size_t w = (size_t)written;
if (off + w >= total) { /* ensure we don't advance beyond buffer */
off = total ? total - 1 : 0;
joined[off] = '\0';
break;
}
off += w;
} }
/* Ensure NUL termination even if loop didn't run */
if (total > 0) joined[(off < total) ? off : (total - 1)] = '\0';
setenv("FUN_ARGS", joined, 1); setenv("FUN_ARGS", joined, 1);
free(joined); free(joined);
} }

View file

@ -259,14 +259,16 @@ static int complete_load_path(char *buf, size_t *len_io) {
if (slash) { if (slash) {
size_t dlen = (size_t)(slash - expanded); size_t dlen = (size_t)(slash - expanded);
if (dlen == 0) { if (dlen == 0) {
strcpy(dirpart, "/"); /* use bounded copy to avoid potential overflow (even though "/" fits) */
snprintf(dirpart, sizeof(dirpart), "%s", "/");
} else { } else {
memcpy(dirpart, expanded, dlen); memcpy(dirpart, expanded, dlen);
dirpart[dlen] = '\0'; dirpart[dlen] = '\0';
} }
snprintf(base, sizeof(base), "%s", slash + 1); snprintf(base, sizeof(base), "%s", slash + 1);
} else { } else {
strcpy(dirpart, "."); /* use bounded copy to avoid potential overflow (even though "." fits) */
snprintf(dirpart, sizeof(dirpart), "%s", ".");
snprintf(base, sizeof(base), "%s", expanded); snprintf(base, sizeof(base), "%s", expanded);
} }

View file

@ -27,6 +27,24 @@ case OP_PROC_SYSTEM: {
push_value(vm, make_int(-1)); push_value(vm, make_int(-1));
break; break;
} }
/* Security hardening: reject commands containing shell metacharacters or control chars
to reduce risk of command injection when using system(3). This preserves simple
command execution like "ls -l" but blocks dangerous constructs like pipes, redirects,
command substitution, etc. */
const char *bad = "&;|$<>`\\\"'()*?[]{}~";
int unsafe = 0;
for (const unsigned char *p = (const unsigned char *)cmd; *p; ++p) {
if (*p < 0x20 || strchr(bad, (int)*p)) { /* control or meta */
unsafe = 1;
break;
}
}
if (unsafe) {
/* refuse to execute potentially unsafe shell command */
push_value(vm, make_int(-1));
free(cmd);
break;
}
int status = system(cmd); int status = system(cmd);
int code = -1; int code = -1;
#ifdef __unix__ #ifdef __unix__