now \uXXXX\uXXXX are encoded separately if together they're not valid UTF-32

This commit is contained in:
cozis
2022-04-24 21:55:00 +02:00
parent f34961a58f
commit 841e3f75fa
+66 -19
View File
@@ -603,34 +603,37 @@ static void *parse_string(context_t *ctx, _Bool raw)
int start = ctx->i-2; int start = ctx->i-2;
assert(start >= 0); assert(start >= 0);
uint32_t rune; uint16_t first_half;
if(!parse_XXXX_after_u(ctx, &first_half))
{ {
uint16_t first_half; spc_free(&spc);
if(!parse_XXXX_after_u(ctx, &first_half)) return NULL;
{
spc_free(&spc);
return NULL;
}
rune = first_half;
} }
int end = ctx->i; int end = ctx->i;
_Bool have_2_parts = 0;
uint16_t second_half;
if(ctx->i+1 < ctx->len && ctx->str[ctx->i] == '\\' if(ctx->i+1 < ctx->len && ctx->str[ctx->i] == '\\'
&& ctx->str[ctx->i+1] == 'u') && ctx->str[ctx->i+1] == 'u')
{ {
have_2_parts = 1;
ctx->i += 2; // Skip the "\u". ctx->i += 2; // Skip the "\u".
uint16_t second_half;
if(!parse_XXXX_after_u(ctx, &second_half)) if(!parse_XXXX_after_u(ctx, &second_half))
{ {
spc_free(&spc); spc_free(&spc);
return NULL; return NULL;
} }
rune = (rune << 16) | second_half;
end = ctx->i; end = ctx->i;
} }
uint32_t rune = first_half;
if(have_2_parts)
rune = (rune << 16) | second_half;
char as_utf8[16]; char as_utf8[16];
int byte_count_as_utf8 = xutf8_sequence_from_utf32_codepoint(as_utf8, sizeof(as_utf8), rune); int byte_count_as_utf8 = xutf8_sequence_from_utf32_codepoint(as_utf8, sizeof(as_utf8), rune);
if(byte_count_as_utf8 < 0) if(byte_count_as_utf8 < 0)
@@ -641,16 +644,60 @@ static void *parse_string(context_t *ctx, _Bool raw)
// UTF-8 text. We'll assume the buffer is // UTF-8 text. We'll assume the buffer is
// big enough to hold any UTF-8 symbol and // big enough to hold any UTF-8 symbol and
// the error is due to malformed unicode. // the error is due to malformed unicode.
xj_preport(ctx->error, ctx->str, start, "Invalid unicode symbol %.*s", end - start, ctx->str + start);
spc_free(&spc);
return NULL;
}
if(!spc_append(&spc, as_utf8, byte_count_as_utf8)) // If the invalid UTF-32 token was invalid
// but composed of two \uXXXX tokens, maybe
// they're valid individually.
if(have_2_parts == 0)
{
xj_preport(ctx->error, ctx->str, start, "Invalid unicode symbol %.*s", end - start, ctx->str + start);
spc_free(&spc);
return NULL;
}
rune = first_half;
byte_count_as_utf8 = xutf8_sequence_from_utf32_codepoint(as_utf8, sizeof(as_utf8), rune);
if(byte_count_as_utf8 < 0)
{
xj_preport(ctx->error, ctx->str, start, "Invalid unicode symbol %.*s", end - start, ctx->str + start);
spc_free(&spc);
return NULL;
}
if(!spc_append(&spc, as_utf8, byte_count_as_utf8))
{
xj_report(ctx->error, "Out of memory");
spc_free(&spc);
return NULL;
}
rune = second_half;
byte_count_as_utf8 = xutf8_sequence_from_utf32_codepoint(as_utf8, sizeof(as_utf8), rune);
if(byte_count_as_utf8 < 0)
{
xj_preport(ctx->error, ctx->str, start, "Invalid unicode symbol %.*s", end - start, ctx->str + start);
spc_free(&spc);
return NULL;
}
if(!spc_append(&spc, as_utf8, byte_count_as_utf8))
{
xj_report(ctx->error, "Out of memory");
spc_free(&spc);
return NULL;
}
}
else
{ {
xj_report(ctx->error, "Out of memory"); if(!spc_append(&spc, as_utf8, byte_count_as_utf8))
spc_free(&spc); {
return NULL; xj_report(ctx->error, "Out of memory");
spc_free(&spc);
return NULL;
}
} }
} }
else else