Bugfix/ubasic-string-tokenizer-null-termination (#1196)
* Fixed tokenizer_string() off-by-one buffer overflow when processing string literals longer than the buffer limit. * Fixed ubasic potential string buffer overflows by using snprintf instead of sprintf. * Fixed ubasic label strings to use UBASIC_LABEL_LEN_MAX as buffer limit. * Fixed ubasic string variables to initialize with zeros. * Fixed compile errors when UBASIC_DEBUG_STRINGVARIABLES is defined. * Added ubasic string variables user accessor API and unit testing for ubasic string variables. * Fixed tokenizer_label() off-by-one buffer overflow when processing string literals longer than the buffer limit.
This commit is contained in:
@@ -383,6 +383,62 @@ static void test_ubasic_math(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify uBASIC string variable handling.
|
||||
* @details Ensures that string variables are truncated at UBASIC_STRINGLEN_MAX
|
||||
* and remain correctly null-terminated when assigned and read back.
|
||||
*/
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(ubasic_tests, test_ubasic_strings)
|
||||
#else
|
||||
static void test_ubasic_strings(void)
|
||||
#endif
|
||||
{
|
||||
struct ubasic_data data = { 0 };
|
||||
const char *program1 =
|
||||
/* program listing with either \0, \n, or ';' at the end of each line.
|
||||
note: indentation is not required */
|
||||
"println 'Demo - Strings'\n"
|
||||
"let a$ = \"1234567890123456789012345678901234567890X\"\n"
|
||||
"print a$\n";
|
||||
const char *program2 =
|
||||
/* program listing with either \0, \n, or ';' at the end of each line.
|
||||
note: indentation is not required */
|
||||
"println 'Demo - Strings'\n"
|
||||
"let z$ = \"1\"\n"
|
||||
"print z$\n";
|
||||
const char *tmpstring;
|
||||
|
||||
ubasic_load_program(&data, program1);
|
||||
zassert_equal(data.status.bit.isRunning, 1, NULL);
|
||||
zassert_equal(data.status.bit.Error, 0, NULL);
|
||||
while (!ubasic_finished(&data)) {
|
||||
ubasic_run_program(&data);
|
||||
}
|
||||
zassert_equal(data.status.bit.Error, 0, NULL);
|
||||
tmpstring = ubasic_ptr_stringvariable(&data, 'a');
|
||||
zassert_not_null(tmpstring, "string variable not found");
|
||||
zassert_equal(
|
||||
strlen(tmpstring), UBASIC_STRINGLEN_MAX - 1, "string length=%d",
|
||||
(int)strlen(tmpstring));
|
||||
zassert_equal(
|
||||
strcmp(tmpstring, "123456789012345678901234567890123456789"), 0,
|
||||
"string value=%s", tmpstring);
|
||||
|
||||
ubasic_load_program(&data, program2);
|
||||
zassert_equal(data.status.bit.isRunning, 1, NULL);
|
||||
zassert_equal(data.status.bit.Error, 0, NULL);
|
||||
while (!ubasic_finished(&data)) {
|
||||
ubasic_run_program(&data);
|
||||
}
|
||||
zassert_equal(data.status.bit.Error, 0, NULL);
|
||||
tmpstring = ubasic_ptr_stringvariable(&data, 'z');
|
||||
zassert_not_null(tmpstring, "string variable not found");
|
||||
zassert_equal(
|
||||
strlen(tmpstring), 1, "string length=%d", (int)strlen(tmpstring));
|
||||
zassert_equal(strcmp(tmpstring, "1"), 0, "string value=%s", tmpstring);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test
|
||||
*/
|
||||
@@ -439,8 +495,8 @@ void test_main(void)
|
||||
{
|
||||
ztest_test_suite(
|
||||
ubasic_tests, ztest_unit_test(test_ubasic),
|
||||
ztest_unit_test(test_ubasic_math), ztest_unit_test(test_ubasic_bacnet),
|
||||
ztest_unit_test(test_ubasic_gpio));
|
||||
ztest_unit_test(test_ubasic_strings), ztest_unit_test(test_ubasic_math),
|
||||
ztest_unit_test(test_ubasic_bacnet), ztest_unit_test(test_ubasic_gpio));
|
||||
|
||||
ztest_run_test_suite(ubasic_tests);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user