---------------------------------------------------------------------- CEscapeString() CHexEscapeString() Utf8SafeCEscapeString() Utf8SafeCHexEscapeString() Copies 'src' to 'dest', escaping dangerous characters using C-style escape sequences. This is very useful for preparing query flags. 'src' and 'dest' should not overlap. The 'Hex' version uses hexadecimal rather than octal sequences. The 'Utf8
| 506 | // Currently only \n, \r, \t, ", ', \ and !ascii_isprint() chars are escaped. |
| 507 | // ---------------------------------------------------------------------- |
| 508 | int CEscapeInternal(const char* src, int src_len, char* dest, |
| 509 | int dest_len, bool use_hex, bool utf8_safe) { |
| 510 | const char* src_end = src + src_len; |
| 511 | int used = 0; |
| 512 | bool last_hex_escape = false; // true if last output char was \xNN |
| 513 | |
| 514 | for (; src < src_end; src++) { |
| 515 | if (dest_len - used < 2) // Need space for two letter escape |
| 516 | return -1; |
| 517 | |
| 518 | bool is_hex_escape = false; |
| 519 | switch (*src) { |
| 520 | case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break; |
| 521 | case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break; |
| 522 | case '\t': dest[used++] = '\\'; dest[used++] = 't'; break; |
| 523 | case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break; |
| 524 | case '\'': dest[used++] = '\\'; dest[used++] = '\''; break; |
| 525 | case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break; |
| 526 | default: |
| 527 | // Note that if we emit \xNN and the src character after that is a hex |
| 528 | // digit then that digit must be escaped too to prevent it being |
| 529 | // interpreted as part of the character code by C. |
| 530 | if ((!utf8_safe || *src < 0x80) && |
| 531 | (!ascii_isprint(*src) || |
| 532 | (last_hex_escape && ascii_isxdigit(*src)))) { |
| 533 | if (dest_len - used < 4) // need space for 4 letter escape |
| 534 | return -1; |
| 535 | sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"), *src); |
| 536 | is_hex_escape = use_hex; |
| 537 | used += 4; |
| 538 | } else { |
| 539 | dest[used++] = *src; |
| 540 | break; |
| 541 | } |
| 542 | } |
| 543 | last_hex_escape = is_hex_escape; |
| 544 | } |
| 545 | |
| 546 | if (dest_len - used < 1) // make sure that there is room for \0 |
| 547 | return -1; |
| 548 | |
| 549 | dest[used] = '\0'; // doesn't count towards return value though |
| 550 | return used; |
| 551 | } |
| 552 | |
| 553 | int CEscapeString(const char* src, int src_len, char* dest, int dest_len) { |
| 554 | return CEscapeInternal(src, src_len, dest, dest_len, false, false); |
no test coverage detected