mirror of
https://github.com/tailix/libkernaux.git
synced 2025-04-14 17:32:55 -04:00
Fix very stupid bug
Never remove const qualified for args without extreme need!
This commit is contained in:
parent
9995d986ac
commit
b9a3c92b8c
3 changed files with 90 additions and 35 deletions
|
@ -61,7 +61,7 @@ RSpec.describe KernAux, '.cmdline' do
|
|||
end
|
||||
end
|
||||
|
||||
xcontext 'when there are too many args' do
|
||||
context 'when there are too many args' do
|
||||
let(:str) { 'a ' * 257 }
|
||||
|
||||
specify do
|
||||
|
@ -70,7 +70,7 @@ RSpec.describe KernAux, '.cmdline' do
|
|||
end
|
||||
end
|
||||
|
||||
xcontext 'when args cause buffer overflow' do
|
||||
context 'when args cause buffer overflow' do
|
||||
let(:str) { 'a' * 4096 }
|
||||
|
||||
specify do
|
||||
|
|
|
@ -17,10 +17,10 @@ enum State {
|
|||
|
||||
bool kernaux_cmdline(
|
||||
const char *const cmdline,
|
||||
char *error_msg,
|
||||
char *const error_msg,
|
||||
size_t *const argc,
|
||||
char **argv,
|
||||
char *buffer,
|
||||
char **const argv,
|
||||
char *const buffer,
|
||||
const size_t argv_count_max,
|
||||
const size_t buffer_size
|
||||
) {
|
||||
|
@ -43,7 +43,6 @@ bool kernaux_cmdline(
|
|||
if (cmdline[0] == '\0') return true;
|
||||
|
||||
enum State state = INITIAL;
|
||||
|
||||
size_t buffer_pos = 0;
|
||||
|
||||
for (size_t index = 0; ; ++index) {
|
||||
|
@ -65,7 +64,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = BACKSLASH;
|
||||
argv[(*argc)++] = buffer;
|
||||
argv[(*argc)++] = &buffer[buffer_pos];
|
||||
} else if (cur == '"') {
|
||||
if (*argc >= argv_count_max) {
|
||||
strcpy(error_msg, "too many args");
|
||||
|
@ -73,7 +72,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = QUOTE;
|
||||
argv[(*argc)++] = buffer;
|
||||
argv[(*argc)++] = &buffer[buffer_pos];
|
||||
} else {
|
||||
if (*argc >= argv_count_max) {
|
||||
strcpy(error_msg, "too many args");
|
||||
|
@ -86,9 +85,8 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = TOKEN;
|
||||
argv[(*argc)++] = buffer;
|
||||
*(buffer++) = cur;
|
||||
++buffer_pos;
|
||||
argv[(*argc)++] = &buffer[buffer_pos];
|
||||
buffer[buffer_pos++] = cur;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -104,7 +102,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = BACKSLASH;
|
||||
argv[(*argc)++] = buffer;
|
||||
argv[(*argc)++] = &buffer[buffer_pos];
|
||||
} else if (cur == '"') {
|
||||
if (*argc >= argv_count_max) {
|
||||
strcpy(error_msg, "too many args");
|
||||
|
@ -112,7 +110,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = QUOTE;
|
||||
argv[(*argc)++] = buffer;
|
||||
argv[(*argc)++] = &buffer[buffer_pos];
|
||||
} else {
|
||||
if (*argc >= argv_count_max) {
|
||||
strcpy(error_msg, "too many args");
|
||||
|
@ -125,9 +123,8 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = TOKEN;
|
||||
argv[(*argc)++] = buffer;
|
||||
*(buffer++) = cur;
|
||||
++buffer_pos;
|
||||
argv[(*argc)++] = &buffer[buffer_pos];
|
||||
buffer[buffer_pos++] = cur;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -139,8 +136,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = FINAL;
|
||||
*(buffer++) = '\0';
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = '\0';
|
||||
} else if (cur == ' ') {
|
||||
if (buffer_pos >= buffer_size) {
|
||||
strcpy(error_msg, "buffer overflow");
|
||||
|
@ -148,8 +144,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = WHITESPACE;
|
||||
*(buffer++) = '\0';
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = '\0';
|
||||
} else if (cur == '\\') {
|
||||
state = BACKSLASH;
|
||||
} else if (cur == '"') {
|
||||
|
@ -161,8 +156,7 @@ bool kernaux_cmdline(
|
|||
goto fail;
|
||||
}
|
||||
|
||||
*(buffer++) = cur;
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = cur;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -177,8 +171,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = TOKEN;
|
||||
*(buffer++) = cur;
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = cur;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -195,16 +188,14 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = WHITESPACE;
|
||||
*(buffer++) = '\0';
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = '\0';
|
||||
} else {
|
||||
if (buffer_pos >= buffer_size) {
|
||||
strcpy(error_msg, "buffer overflow");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*(buffer++) = cur;
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = cur;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -219,8 +210,7 @@ bool kernaux_cmdline(
|
|||
}
|
||||
|
||||
state = QUOTE;
|
||||
*(buffer++) = cur;
|
||||
++buffer_pos;
|
||||
buffer[buffer_pos++] = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ARGV_COUNT_MAX 100
|
||||
|
@ -231,6 +232,56 @@ int main()
|
|||
test("\"", 0, 0, false, "EOL inside quote", 0, NULL);
|
||||
test("\"foo", 0, 0, false, "EOL inside quote", 0, NULL);
|
||||
|
||||
test(
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
"",
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
test("a", 1, 0, true, "", 1, NULL);
|
||||
test("a a", 1, 0, false, "too many args", 0, NULL);
|
||||
test("a a ", 1, 0, false, "too many args", 0, NULL);
|
||||
test("a a", 2, 0, true, "", 2, NULL);
|
||||
test("a a ", 2, 0, true, "", 2, NULL);
|
||||
test("a a a", 2, 0, false, "too many args", 0, NULL);
|
||||
test("a a a ", 2, 0, false, "too many args", 0, NULL);
|
||||
test("a a a", 3, 0, true, "", 3, NULL);
|
||||
test("a a a ", 3, 0, true, "", 3, NULL);
|
||||
test("a a a a", 3, 0, false, "too many args", 0, NULL);
|
||||
test("a a a a ", 3, 0, false, "too many args", 0, NULL);
|
||||
test("a a a a", 4, 0, true, "", 4, NULL);
|
||||
test("a a a a ", 4, 0, true, "", 4, NULL);
|
||||
test("a a a a a", 4, 0, false, "too many args", 0, NULL);
|
||||
test("a a a a a ", 4, 0, false, "too many args", 0, NULL);
|
||||
test("a a a a a", 5, 0, true, "", 5, NULL);
|
||||
test("a a a a a ", 5, 0, true, "", 5, NULL);
|
||||
test("a a a a a a", 5, 0, false, "too many args", 0, NULL);
|
||||
test("a a a a a a ", 5, 0, false, "too many args", 0, NULL);
|
||||
test("a a a a a a", 6, 0, true, "", 6, NULL);
|
||||
test("a a a a a a ", 6, 0, true, "", 6, NULL);
|
||||
|
||||
{
|
||||
char *const buffer = malloc(4096);
|
||||
memset(buffer, 'a', 4096 - 1);
|
||||
buffer[4096 - 1] = '\0';
|
||||
// 4095 of "a"
|
||||
test(buffer, 256, 4096, true, "", 1, NULL);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
{
|
||||
char *const buffer = malloc(4096 + 1);
|
||||
memset(buffer, 'a', 4096);
|
||||
buffer[4096] = '\0';
|
||||
// 4096 of "a"
|
||||
test(buffer, 256, 4096, false, "buffer overflow", 0, NULL);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -247,10 +298,18 @@ void test(
|
|||
if (argv_count_max == 0) argv_count_max = ARGV_COUNT_MAX;
|
||||
if (buffer_size == 0) buffer_size = BUFFER_SIZE;
|
||||
|
||||
char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX];
|
||||
char *error_msg = malloc(KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
|
||||
size_t argc = 1234;
|
||||
char *argv[argv_count_max];
|
||||
char buffer[buffer_size];
|
||||
char **const argv = malloc(sizeof(char*) * argv_count_max);
|
||||
char *const buffer = malloc(buffer_size);
|
||||
|
||||
assert(error_msg);
|
||||
assert(argv);
|
||||
assert(buffer);
|
||||
|
||||
memset(error_msg, 'a', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
|
||||
memset(argv, 'a', sizeof(char*) * argv_count_max);
|
||||
memset(buffer, 'a', buffer_size);
|
||||
|
||||
assert(
|
||||
kernaux_cmdline(
|
||||
|
@ -267,11 +326,17 @@ void test(
|
|||
assert(strcmp(error_msg, expected_error_msg) == 0);
|
||||
assert(argc == expected_argc);
|
||||
|
||||
for (size_t index = 0; index < argc; ++index) {
|
||||
assert(strcmp(argv[index], expected_argv[index]) == 0);
|
||||
if (expected_argv) {
|
||||
for (size_t index = 0; index < argc; ++index) {
|
||||
assert(strcmp(argv[index], expected_argv[index]) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t index = argc; index < argv_count_max; ++index) {
|
||||
assert(argv[index] == NULL);
|
||||
}
|
||||
|
||||
free(error_msg);
|
||||
free(argv);
|
||||
free(buffer);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue