boot: don't unquote an empty value in line_get_key_value()

de0da85d41 switched the unquote check to strchr8(QUOTES, value[0]),
which is not equivalent to the old explicit comparison for an empty
value: strchr8(), like strchr(3), returns a pointer to the haystack's
terminating NUL when the needle is '\0', so strchr8(QUOTES, '\0') is
non-NULL. For a line whose separator is the last byte (e.g. "ID=") the
split leaves value[0] == '\0' and line[linelen - 1] == '\0' too, so both
conjuncts hold and value++ steps one byte past the value's terminator.

Follow-up for de0da85d41
This commit is contained in:
Luca Boccassi
2026-07-03 15:19:39 +01:00
parent 7b7599b72d
commit 7378b51f66
2 changed files with 7 additions and 1 deletions
+1 -1
View File
@@ -500,7 +500,7 @@ char* line_get_key_value(char *s, const char *sep, size_t *pos, char **ret_key,
value++;
/* unquote */
if (strchr8(QUOTES, value[0]) && line[linelen - 1] == value[0]) {
if (value[0] != '\0' && strchr8(QUOTES, value[0]) && line[linelen - 1] == value[0]) {
value++;
line[linelen - 1] = '\0';
}
+6
View File
@@ -590,6 +590,7 @@ TEST(line_get_key_value) {
" also\tused \r\n"
"for \"the conf\"\n"
"format\t !!";
char s3[] = "ID=";
size_t pos = 0;
char *key, *value;
@@ -611,6 +612,11 @@ TEST(line_get_key_value) {
ASSERT_TRUE(streq8(value, " stripping # with comments"));
ASSERT_NULL(line_get_key_value(s1, "=", &pos, &key, &value));
pos = 0;
ASSERT_NOT_NULL(line_get_key_value(s3, "=", &pos, &key, &value));
ASSERT_TRUE(streq8(key, "ID"));
ASSERT_TRUE(streq8(value, ""));
pos = 0;
ASSERT_NOT_NULL(line_get_key_value(s2, " \t", &pos, &key, &value));
ASSERT_TRUE(streq8(key, "this"));