Fix very stupid bug

Never remove const qualified for args without extreme need!
This commit is contained in:
Alex Kotov 2022-01-23 03:32:52 +05:00
parent 9995d986ac
commit b9a3c92b8c
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
3 changed files with 90 additions and 35 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}