Some small injection fixes. (0.42.2)
This commit is contained in:
parent
752f0efdd1
commit
1b90493a7a
4 changed files with 42 additions and 7 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
21
src/fun.c
21
src/fun.c
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue