Skip to content

Instantly share code, notes, and snippets.

@dtoma
Last active September 29, 2016 06:25
Show Gist options
  • Save dtoma/c8489c36ff6cd6caa61f50e2980da5ac to your computer and use it in GitHub Desktop.
Save dtoma/c8489c36ff6cd6caa61f50e2980da5ac to your computer and use it in GitHub Desktop.
safer sscanf
#include <cstdio>
template <typename ... Args>
bool safe_sscanf(char const* s, char const* fmt, Args*... args)
{
constexpr auto len = sizeof...(args);
auto n = sscanf(s, fmt, args...);
if (n != len)
{
printf("sscanf error: captured %d instead of %zu - string was [%s], format was [%s]\n", n, len, s, fmt);
return false;
}
return true;
}
int main()
{
int a = 0, b = 0, c = 0;
if (!safe_sscanf("23:59:59", "%2u:%2u:%2u", &a, &b, &c))
{
// If we'd passed "23:59::59" as input, we'd have gotten an error:
// > sscanf error: captured 2 instead of 3 - string was [23:59::59], format was [%2u:%2u:%2u]
return 1;
}
// This would still give us an unwanted result if the input was, for example, "2:3:59:59": we'd get [2, 3, 59],
// because %2 means "up to 2", not "exactly 2".
// For input validation, regexes are more powerful.
}
@dtoma
Copy link
Author

dtoma commented Sep 28, 2016

gcc7 -O3 -Wall -Wextra -pedantic -Wformat -std=c++11

.LC0:
        .string "%2u:%2u:%2u"
.LC1:
        .string "23:59:59"
.LC2:
        .string "sscanf error: captured %d instead of %zu - string was [%s], format was [%s]\n"
main:
        sub     rsp, 24
        xor     eax, eax
        mov     esi, OFFSET FLAT:.LC0
        lea     r8, [rsp+12]
        lea     rcx, [rsp+8]
        lea     rdx, [rsp+4]
        mov     edi, OFFSET FLAT:.LC1
        mov     DWORD PTR [rsp+4], 0
        mov     DWORD PTR [rsp+8], 0
        mov     DWORD PTR [rsp+12], 0
        call    sscanf
        cmp     eax, 3
        je      .L6
        mov     esi, eax
        mov     r8d, OFFSET FLAT:.LC0
        mov     ecx, OFFSET FLAT:.LC1
        mov     edx, 3
        mov     edi, OFFSET FLAT:.LC2
        xor     eax, eax
        call    printf
        mov     eax, 1
.L1:
        add     rsp, 24
        ret
.L6:
        xor     eax, eax
        jmp     .L1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment