Skip to content

Commit 669e6f6

Browse files
committed
Use octal escapes to avoid invalid C-strings like "\xFFa"
1 parent 53851dd commit 669e6f6

File tree

2 files changed

+91
-5
lines changed

2 files changed

+91
-5
lines changed

src/Format.cc

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,91 @@ static ErrorCode ForEachEscaped(char const* str, size_t len, F func)
348348
for (size_t i = 0; i < len; ++i)
349349
{
350350
char const ch = str[i];
351+
#if 0
352+
switch (ch)
353+
{
354+
case '\a':
355+
if (Failed ec = func('\\'))
356+
return ec;
357+
if (Failed ec = func('a'))
358+
return ec;
359+
break;
360+
case '\b':
361+
if (Failed ec = func('\\'))
362+
return ec;
363+
if (Failed ec = func('b'))
364+
return ec;
365+
break;
366+
case '\f':
367+
if (Failed ec = func('\\'))
368+
return ec;
369+
if (Failed ec = func('f'))
370+
return ec;
371+
break;
372+
case '\n':
373+
if (Failed ec = func('\\'))
374+
return ec;
375+
if (Failed ec = func('n'))
376+
return ec;
377+
break;
378+
case '\r':
379+
if (Failed ec = func('\\'))
380+
return ec;
381+
if (Failed ec = func('r'))
382+
return ec;
383+
break;
384+
case '\t':
385+
if (Failed ec = func('\\'))
386+
return ec;
387+
if (Failed ec = func('t'))
388+
return ec;
389+
break;
390+
case '\v':
391+
if (Failed ec = func('\\'))
392+
return ec;
393+
if (Failed ec = func('v'))
394+
return ec;
395+
break;
396+
case '\\':
397+
if (Failed ec = func('\\'))
398+
return ec;
399+
if (Failed ec = func('\\'))
400+
return ec;
401+
break;
402+
case '\'':
403+
if (Failed ec = func('\\'))
404+
return ec;
405+
if (Failed ec = func('\''))
406+
return ec;
407+
break;
408+
case '"':
409+
if (Failed ec = func('\\'))
410+
return ec;
411+
if (Failed ec = func('"'))
412+
return ec;
413+
break;
414+
default:
415+
if (IsASCIIPrintable(ch))
416+
{
417+
if (Failed ec = func(ch))
418+
return ec;
419+
}
420+
else
421+
{
422+
unsigned char uch = static_cast<unsigned char>(ch);
423+
424+
if (Failed ec = func('\\'))
425+
return ec;
426+
if (Failed ec = func(kUpperDigits[(uch >> 6) ]))
427+
return ec;
428+
if (Failed ec = func(kUpperDigits[(uch >> 3) & 0x7]))
429+
return ec;
430+
if (Failed ec = func(kUpperDigits[(uch >> 0) & 0x7]))
431+
return ec;
432+
}
433+
break;
434+
}
435+
#else
351436
if (IsASCIIPrintable(ch))
352437
{
353438
if (Failed ec = func(ch))
@@ -359,13 +444,14 @@ static ErrorCode ForEachEscaped(char const* str, size_t len, F func)
359444

360445
if (Failed ec = func('\\'))
361446
return ec;
362-
if (Failed ec = func('x'))
447+
if (Failed ec = func(kUpperDigits[(uch >> 6) ]))
363448
return ec;
364-
if (Failed ec = func(kUpperDigits[(uch >> 4) & 0xF]))
449+
if (Failed ec = func(kUpperDigits[(uch >> 3) & 0x7]))
365450
return ec;
366-
if (Failed ec = func(kUpperDigits[(uch >> 0) & 0xF]))
451+
if (Failed ec = func(kUpperDigits[(uch >> 0) & 0x7]))
367452
return ec;
368453
}
454+
#endif
369455
}
370456

371457
return {};

test/Test.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,12 +429,12 @@ TEST_CASE("Strings quoted")
429429
CHECK("hello" == FormatArgs("{}", arr1));
430430
}
431431

432-
TEST_CASE("Strings hex escaped")
432+
TEST_CASE("Strings escaped")
433433
{
434434
// U+1F60D SMILING FACE WITH HEART-SHAPED EYES
435435

436436
CHECK(u8"😍" == FormatArgs("{}", u8"😍"));
437-
CHECK(R"(hello \xF0\x9F\x98\x8D)" == FormatArgs("{:x}", u8"hello 😍"));
437+
CHECK(R"(hello \360\237\230\215a)" == FormatArgs("{:x}", u8"hello 😍a"));
438438
}
439439

440440
TEST_CASE("Ints")

0 commit comments

Comments
 (0)