Home > Mobile >  How do I escape the `\0 character` or why is my method not working? (C , GTest)
How do I escape the `\0 character` or why is my method not working? (C , GTest)

Time:08-06

I am writing a function to test going from URL to a query name format. For example, the URL "google.com" should turn into "\x6google\x3com\0". But if I want to test matching this I thought I just had to do something like this:

    // Test first that "google.com" becomes "\6google\3com\0"
    EXPECT_EQ(
        test_dns_querier->url_to_qname(url_test),
        "\x6google\x3""com\\0" // Escaped
    );

The first \x6 is to match against the hex character in the qname format. Same with \x3. Then after \x3 I needed to stop and start a new string since the 'c' in 'com' gets mistaken as a hex character. Then I use '\' in order to get a backslash and finally a '0', but here is where it goes wrong (see the ctest output below).

8: Expected equality of these values:
8:   test_dns_querier->url_to_qname(url_test)
8:     Which is: "\x6google\x3" "com\0"
8:   "\x6google\x3""com\\0"
8:     Which is: "\x6google\x3" "com\\0"
8: [  FAILED  ] dns_query_tests.DemonstrateQNameURLConverision (0 ms)

For some reason my double backslash does not work. And when I remove one it still escapes the '0' in '\0'.

Why does the typical '\' not work in this case?

CodePudding user response:

To embed zero in a string literal, write \0 or \x00. But in most contexts, char arrays (including string literals) are treated as C strings, i.e. zero-terminated. Thus the first embedded zero will be considered as string end and not its part. Indeed, that is the only way as the size is not passed along string (even string literal, although it has one).

So, you need:

  1. Return your string from url_to_qname as something that supports embedded zeroes. std::string is okay.
  2. Pass the string literal in a similar way. In C 17, you can use std::string_view for that: write your literal as "\x06google\x03com\x00"sv (after using namespace std::literals or likewise) and it will be converted to std::string_view in a way preserving embedded zeroes. Before C 17 that would need a bit of template or macro magic though, as things like std::string("\x06google\x03com\x00") don’t work (that constructor supports C strings only).

UPDATE: as @273K pointed out there is also ""s which is available a bit earlier, since C 14.

  • Related