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