Disallow producing NULL character with escape sequences NULL usually terminates the strings; allowing to produce it via escape sequences may lead to undefined behaviour. - Make NULL escape sequences (e.g. `\0` and `\x0`) invalid. - Add corresponding test. - Introduce the new message: XKB_WARNING_INVALID_ESCAPE_SEQUENCE.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
diff --git a/doc/message-registry.md b/doc/message-registry.md
index a3be5c1..24b2ffc 100644
--- a/doc/message-registry.md
+++ b/doc/message-registry.md
@@ -6,7 +6,7 @@ NOTE: This file has been generated automatically by “update-message-registry.p
-->
This page lists the warnings and errors generated by xkbcommon.
-There are currently 52 entries.
+There are currently 53 entries.
@todo The documentation of the log messages is a work in progress.
@@ -24,6 +24,7 @@ There are currently 52 entries.
| [XKB-150] | `wrong-statement-type` | The type of the statement is not allowed in the context | Error |
| [XKB-172] | `unsupported-geometry-section` | Geometry sections are not supported | Warning |
| [XKB-183] | `cannot-infer-key-type` | Warn if no key type can be inferred | Warning |
+| [XKB-193] | `invalid-escape-sequence` | Invalid escape sequence in a string | Warning |
| [XKB-195] | `illegal-key-type-preserve-result` | The result of a key type “preserve” entry must be a subset of its input modifiers. | Warning |
| [XKB-203] | `invalid-include-statement` | Syntax error in the include statement | Error |
| [XKB-206] | `invalid-modmap-entry` | A modmap entry is invalid | Error |
@@ -198,6 +199,14 @@ key <AB08> {[ comma, semicolon, periodcentered, multiply ]};
<dt>Summary</dt><dd>Warn if no key type can be inferred</dd>
</dl>
+### XKB-193 – Invalid escape sequence {#XKB-193}
+
+<dl>
+ <dt>Since</dt><dd>1.0.0</dd>
+ <dt>Type</dt><dd>Warning</dd>
+ <dt>Summary</dt><dd>Invalid escape sequence in a string</dd>
+</dl>
+
### XKB-195 – Illegal key type preserve result {#XKB-195}
<dl>
@@ -624,6 +633,7 @@ The modifiers used in `map` or `preserve` entries should be declared using the e
[XKB-150]: @ref XKB-150
[XKB-172]: @ref XKB-172
[XKB-183]: @ref XKB-183
+[XKB-193]: @ref XKB-193
[XKB-195]: @ref XKB-195
[XKB-203]: @ref XKB-203
[XKB-206]: @ref XKB-206
diff --git a/doc/message-registry.yaml b/doc/message-registry.yaml
index 880c2f6..9f4c450 100644
--- a/doc/message-registry.yaml
+++ b/doc/message-registry.yaml
@@ -100,6 +100,11 @@
added: ALWAYS
type: warning
description: "Warn if no key type can be inferred"
+- id: "invalid-escape-sequence"
+ code: 193
+ added: ALWAYS
+ type: warning
+ description: "Invalid escape sequence in a string"
- id: "illegal-key-type-preserve-result"
code: 195
added: ALWAYS
diff --git a/src/compose/parser.c b/src/compose/parser.c
index e1b81de..57be1bd 100644
--- a/src/compose/parser.c
+++ b/src/compose/parser.c
@@ -178,13 +178,24 @@ skip_more_whitespace_and_comments:
scanner_buf_append(s, '"');
}
else if (scanner_chr(s, 'x') || scanner_chr(s, 'X')) {
- if (scanner_hex(s, &o))
+ if (scanner_hex(s, &o) && is_valid_char((char) o)) {
scanner_buf_append(s, (char) o);
- else
- scanner_warn(s, "illegal hexadecimal escape sequence in string literal");
+ } else {
+ // [TODO] actually show the sequence
+ scanner_warn_with_code(s,
+ XKB_WARNING_INVALID_ESCAPE_SEQUENCE,
+ "illegal hexadecimal escape sequence in string literal");
+ }
}
else if (scanner_oct(s, &o)) {
- scanner_buf_append(s, (char) o);
+ if (is_valid_char((char) o)) {
+ scanner_buf_append(s, (char) o);
+ } else {
+ // [TODO] actually show the sequence
+ scanner_warn_with_code(s,
+ XKB_WARNING_INVALID_ESCAPE_SEQUENCE,
+ "illegal octal escape sequence in string literal");
+ }
}
else {
scanner_warn(s, "unknown escape sequence (%c) in string literal", scanner_peek(s));
diff --git a/src/messages-codes.h b/src/messages-codes.h
index 5d8c84c..af7bb93 100644
--- a/src/messages-codes.h
+++ b/src/messages-codes.h
@@ -36,6 +36,8 @@ enum xkb_message_code {
XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION = 172,
/** Warn if no key type can be inferred */
XKB_WARNING_CANNOT_INFER_KEY_TYPE = 183,
+ /** Invalid escape sequence in a string */
+ XKB_WARNING_INVALID_ESCAPE_SEQUENCE = 193,
/** The result of a key type “preserve” entry must be a subset of its input modifiers. */
XKB_WARNING_ILLEGAL_KEY_TYPE_PRESERVE_RESULT = 195,
/** Syntax error in the include statement */
diff --git a/src/utils.h b/src/utils.h
index fdf758b..aa7969c 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -65,6 +65,15 @@
#define STRINGIFY(x) #x
#define STRINGIFY2(x) STRINGIFY(x)
+/* Check if a character is valid in a string literal */
+static inline bool
+is_valid_char(char c)
+{
+ /* Currently we only check for NULL character, but this could be extended
+ * in the future to further ASCII control characters. */
+ return c != 0;
+}
+
char
to_lower(char c);
diff --git a/src/xkbcomp/scanner.c b/src/xkbcomp/scanner.c
index e9d503c..800d2d0 100644
--- a/src/xkbcomp/scanner.c
+++ b/src/xkbcomp/scanner.c
@@ -98,7 +98,15 @@ skip_more_whitespace_and_comments:
else if (scanner_chr(s, 'f')) scanner_buf_append(s, '\f');
else if (scanner_chr(s, 'v')) scanner_buf_append(s, '\v');
else if (scanner_chr(s, 'e')) scanner_buf_append(s, '\033');
- else if (scanner_oct(s, &o)) scanner_buf_append(s, (char) o);
+ else if (scanner_oct(s, &o)) {
+ if (is_valid_char((char) o)) {
+ scanner_buf_append(s, (char) o);
+ } else {
+ scanner_warn_with_code(s,
+ XKB_WARNING_INVALID_ESCAPE_SEQUENCE,
+ "invalid octal escape sequence: \\%o", o);
+ }
+ }
else {
// TODO: display actual sequence! See: scanner_peek(s).
// require escaping any potential control character
diff --git a/test/compose.c b/test/compose.c
index 5e7cba0..3d45805 100644
--- a/test/compose.c
+++ b/test/compose.c
@@ -684,6 +684,17 @@ test_traverse(struct xkb_context *ctx)
xkb_compose_table_unref(table);
}
+static void
+test_escape_sequences(struct xkb_context *ctx)
+{
+ const char *table_string = "<o> <e> : \"f\\x0o\\0o\" X\n";
+
+ assert(test_compose_seq_buffer(ctx, table_string,
+ XKB_KEY_o, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
+ XKB_KEY_e, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X,
+ XKB_KEY_NoSymbol));
+}
+
int
main(int argc, char *argv[])
{
@@ -717,6 +728,7 @@ main(int argc, char *argv[])
test_include(ctx);
test_override(ctx);
test_traverse(ctx);
+ test_escape_sequences(ctx);
xkb_context_unref(ctx);
return 0;
diff --git a/test/data/keymaps/invalid-escape-sequence.xkb b/test/data/keymaps/invalid-escape-sequence.xkb
new file mode 100644
index 0000000..99349ec
--- /dev/null
+++ b/test/data/keymaps/invalid-escape-sequence.xkb
@@ -0,0 +1,9 @@
+xkb_keymap {
+ // The following include statement has an octal escape sequence that
+ // must be ignored. Else it would insert a NULL character and thus
+ // truncates the string to "evde", while we expect "evdev+aliases(qwerty)".
+ xkb_keycodes { include "evde\0v+aliases(qwerty)" };
+ xkb_types { include "complete" };
+ xkb_compat { include "complete" };
+ xkb_symbols { include "pc+us" };
+};
diff --git a/test/filecomp.c b/test/filecomp.c
index 5fc7477..e73dc4c 100644
--- a/test/filecomp.c
+++ b/test/filecomp.c
@@ -48,6 +48,7 @@ main(void)
assert(test_file(ctx, "keymaps/quartz.xkb"));
assert(test_file(ctx, "keymaps/no-aliases.xkb"));
assert(test_file(ctx, "keymaps/modmap-none.xkb"));
+ assert(test_file(ctx, "keymaps/invalid-escape-sequence.xkb"));
assert(!test_file(ctx, "keymaps/divide-by-zero.xkb"));
assert(!test_file(ctx, "keymaps/bad.xkb"));
diff --git a/tools/messages.c b/tools/messages.c
index fc3b411..9230dfd 100644
--- a/tools/messages.c
+++ b/tools/messages.c
@@ -48,6 +48,7 @@ static const struct xkb_message_entry xkb_messages[] = {
{XKB_ERROR_WRONG_STATEMENT_TYPE, "Wrong statement type"},
{XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION, "Unsupported geometry section"},
{XKB_WARNING_CANNOT_INFER_KEY_TYPE, "Cannot infer key type"},
+ {XKB_WARNING_INVALID_ESCAPE_SEQUENCE, "Invalid escape sequence"},
{XKB_WARNING_ILLEGAL_KEY_TYPE_PRESERVE_RESULT, "Illegal key type preserve result"},
{XKB_ERROR_INVALID_INCLUDE_STATEMENT, "Invalid include statement"},
{XKB_ERROR_INVALID_MODMAP_ENTRY, "Invalid modmap entry"},