Skip to content

Commit 3a12afd

Browse files
TartanLlamazkat
andcommitted
fix: Find invalid characters after nul bytes in KV store keys (fastly#1464)
Co-authored-by: Kat Marchán <kzm@zkat.tech> Co-authored-by: Kat Marchán <kat.marchan@fastly.com>
1 parent 03d1c8a commit 3a12afd

3 files changed

Lines changed: 16 additions & 4 deletions

File tree

integration-tests/js-compute/fixtures/module-mode/src/kv-store.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,16 @@ const debug = sdkVersion.endsWith('-debug');
504504
}
505505
},
506506
);
507+
routes.set('/kv-store/put/key-parameter-containing-nul-byte', async () => {
508+
await assertRejects(
509+
async () => {
510+
let store = new KVStore(KV_STORE_NAME);
511+
await store.put('a\x00;b', '');
512+
},
513+
TypeError,
514+
`KVStore key can not contain ; character`,
515+
);
516+
});
507517
routes.set('/kv-store/put/value-parameter-as-undefined', async () => {
508518
const store = new KVStore(KV_STORE_NAME);
509519
let result = store.put('undefined', undefined);

integration-tests/js-compute/fixtures/module-mode/tests.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@
325325
"GET /kv-store/put/key-parameter-containing-special-characters": {
326326
"flake": true
327327
},
328+
"GET /kv-store/put/key-parameter-containing-nul-byte": { "flake": true },
328329
"GET /kv-store/put/value-parameter-as-undefined": { "flake": true },
329330
"GET /kv-store/put/value-parameter-not-supplied": { "flake": true },
330331
"GET /kv-store/put/value-parameter-readablestream-empty": { "flake": true },

runtime/fastly/builtins/kv-store.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ api::Engine *ENGINE;
4141

4242
std::string_view bad_chars{"#;?^|\n\r"};
4343

44-
std::optional<char> find_invalid_character_for_kv_store_key(const char *str) {
44+
std::optional<char> find_invalid_character_for_kv_store_key(const char *str, size_t len) {
4545
std::optional<char> res;
4646

47-
std::string_view view{str, strlen(str)};
47+
std::string_view view{str, len};
4848

4949
auto it = std::find_if(view.begin(), view.end(),
5050
[](auto c) { return bad_chars.find(c) != std::string_view::npos; });
@@ -195,7 +195,7 @@ bool parse_and_validate_key(JSContext *cx, const char *key, size_t len) {
195195
}
196196

197197
auto key_chars = key;
198-
auto res = find_invalid_character_for_kv_store_key(key_chars);
198+
auto res = find_invalid_character_for_kv_store_key(key_chars, len);
199199
if (res.has_value()) {
200200
std::string character;
201201
switch (res.value()) {
@@ -231,7 +231,8 @@ bool parse_and_validate_key(JSContext *cx, const char *key, size_t len) {
231231
return false;
232232
}
233233

234-
if (strcmp(key_chars, ".") == 0 || strcmp(key_chars, "..") == 0) {
234+
if ((len == 1 && key_chars[0] == '.') ||
235+
(len == 2 && key_chars[0] == '.' && key_chars[1] == '.')) {
235236
JS_ReportErrorNumberASCII(cx, FastlyGetErrorMessage, nullptr, JSMSG_KV_STORE_KEY_RELATIVE);
236237
return false;
237238
}

0 commit comments

Comments
 (0)