diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2024-03-10 13:15:55 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-03-15 17:21:35 +0100 |
commit | bc3eb7b52789bdea457e4fdff6e25da340c88901 (patch) | |
tree | b2db680b20661bd7f454f1e03ed10481b2a1e2ab | |
parent | plug potential memory leak in error code path (diff) | |
download | openssl-bc3eb7b52789bdea457e4fdff6e25da340c88901.tar.xz openssl-bc3eb7b52789bdea457e4fdff6e25da340c88901.zip |
Try to fix intermittent CI failures in quic_multistream test
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23807)
-rw-r--r-- | ssl/quic/json_enc.c | 45 | ||||
-rw-r--r-- | test/json_test.c | 22 |
2 files changed, 58 insertions, 9 deletions
diff --git a/ssl/quic/json_enc.c b/ssl/quic/json_enc.c index 5222a4560e..650247f869 100644 --- a/ssl/quic/json_enc.c +++ b/ssl/quic/json_enc.c @@ -626,6 +626,7 @@ json_write_qstring_inner(OSSL_JSON_ENC *json, const char *str, size_t str_len, int nul_term) { char c, *o, obuf[7]; + unsigned char *u_str; int i; size_t j; @@ -634,9 +635,9 @@ json_write_qstring_inner(OSSL_JSON_ENC *json, const char *str, size_t str_len, json_write_char(json, '"'); - for (j = 0; (nul_term && *str != '\0') - || (!nul_term && j < str_len); ++str, ++j) { + for (j = nul_term ? strlen(str) : str_len; j > 0; str++, j--) { c = *str; + u_str = (unsigned char*)str; switch (c) { case '\n': o = "\\n"; break; case '\r': o = "\\r"; break; @@ -646,15 +647,45 @@ json_write_qstring_inner(OSSL_JSON_ENC *json, const char *str, size_t str_len, case '"': o = "\\\""; break; case '\\': o = "\\\\"; break; default: - if ((unsigned char)c >= 0x80) { - json_raise_error(json); - return; + /* valid UTF-8 sequences according to RFC-3629 */ + if (u_str[0] >= 0xc2 && u_str[0] <= 0xdf && j >= 2 + && u_str[1] >= 0x80 && u_str[1] <= 0xbf) { + memcpy(obuf, str, 2); + obuf[2] = '\0'; + str++, j--; + o = obuf; + break; + } + if (u_str[0] >= 0xe0 && u_str[0] <= 0xef && j >= 3 + && u_str[1] >= 0x80 && u_str[1] <= 0xbf + && u_str[2] >= 0x80 && u_str[2] <= 0xbf + && !(u_str[0] == 0xe0 && u_str[1] <= 0x9f) + && !(u_str[0] == 0xed && u_str[1] >= 0xa0)) { + memcpy(obuf, str, 3); + obuf[3] = '\0'; + str += 2; + j -= 2; + o = obuf; + break; + } + if (u_str[0] >= 0xf0 && u_str[0] <= 0xf4 && j >= 4 + && u_str[1] >= 0x80 && u_str[1] <= 0xbf + && u_str[2] >= 0x80 && u_str[2] <= 0xbf + && u_str[3] >= 0x80 && u_str[3] <= 0xbf + && !(u_str[0] == 0xf0 && u_str[1] <= 0x8f) + && !(u_str[0] == 0xf4 && u_str[1] >= 0x90)) { + memcpy(obuf, str, 4); + obuf[4] = '\0'; + str += 3; + j -= 3; + o = obuf; + break; } - if ((unsigned char)c < 0x20 || (unsigned char)c >= 0x7f) { + if (u_str[0] < 0x20 || u_str[0] >= 0x7f) { obuf[0] = '\\'; obuf[1] = 'u'; for (i = 0; i < 4; ++i) - obuf[2 + i] = hex_digit((c >> ((3 - i) * 4)) & 0x0F); + obuf[2 + i] = hex_digit((u_str[0] >> ((3 - i) * 4)) & 0x0F); obuf[6] = '\0'; o = obuf; } else { diff --git a/test/json_test.c b/test/json_test.c index 5a054b7c6d..db3038d766 100644 --- a/test/json_test.c +++ b/test/json_test.c @@ -427,8 +427,23 @@ END_SCRIPT_EXPECTING_S("{\"x\":") BEGIN_SCRIPT(err_utf8, "error test: only basic ASCII supported", 0) OPJ_STR("\x80") - OP_ASSERT_ERROR(1) -END_SCRIPT_EXPECTING_S("\"") + OP_ASSERT_ERROR(0) +END_SCRIPT_EXPECTING_S("\"\\u0080\"") + +BEGIN_SCRIPT(utf8_2, "test: valid UTF-8 2byte supported", 0) + OPJ_STR("low=\xc2\x80, high=\xdf\xbf") + OP_ASSERT_ERROR(0) +END_SCRIPT_EXPECTING_S("\"low=\xc2\x80, high=\xdf\xbf\"") + +BEGIN_SCRIPT(utf8_3, "test: valid UTF-8 3byte supported", 0) + OPJ_STR("low=\xe0\xa0\x80, high=\xef\xbf\xbf") + OP_ASSERT_ERROR(0) +END_SCRIPT_EXPECTING_S("\"low=\xe0\xa0\x80, high=\xef\xbf\xbf\"") + +BEGIN_SCRIPT(utf8_4, "test: valid UTF-8 4byte supported", 0) + OPJ_STR("low=\xf0\x90\xbf\xbf, high=\xf4\x8f\xbf\xbf") + OP_ASSERT_ERROR(0) +END_SCRIPT_EXPECTING_S("\"low=\xf0\x90\xbf\xbf, high=\xf4\x8f\xbf\xbf\"") BEGIN_SCRIPT(ijson_int, "I-JSON: large integer", OSSL_JSON_FLAG_IJSON) OPJ_BEGIN_A() @@ -508,6 +523,9 @@ static const info_func scripts[] = { SCRIPT(err_obj_multi_key) SCRIPT(err_obj_no_value) SCRIPT(err_utf8) + SCRIPT(utf8_2) + SCRIPT(utf8_3) + SCRIPT(utf8_4) SCRIPT(ijson_int) SCRIPT(multi_item) SCRIPT(seq) |