Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop in bool has_nonspace_chars(const std::string &s) #20193

Open
Arpan3323 opened this issue Jan 18, 2025 · 2 comments
Open

Infinite loop in bool has_nonspace_chars(const std::string &s) #20193

Arpan3323 opened this issue Jan 18, 2025 · 2 comments

Comments

@Arpan3323
Copy link

Describe the bug

The function linked below tends to get into an infinite loop if s[0] == ' '. In other words, if s[0] is a space character, the function gets into an infinite loop regardless of following characters in the string being non-space. This is because iter is not incremented.

bool
has_nonspace_chars(const std::string &s)
{
std::string::const_iterator iter = s.begin();
while(iter != s.end())
{
if(!isspace(*iter))
{
return true;
}
}
return false;
}

Test for reproducing the bug

Both of these tests result in an infinite loop that is terminated by a 120 seconds timeout instrumented by me on the test executables.

Test 1

extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size)
{
  if(Size < 4) return 0;
  std::string fuzzedInp(reinterpret_cast<const char*>(Data),Size);
  std::string inp = " " + fuzzedInp;
  has_nonspace_chars(inp);
  return 0;
}

Test 2

extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size)
{
  has_nonspace_chars(" a");
  return 0;
}

Crash report

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 346469114
INFO: Loaded 1 modules   (64 inline 8-bit counters): 64 [0x561d3c23c100, 0x561d3c23c140), 
INFO: Loaded 1 PC tables (64 PCs): 64 [0x561d3c23c140,0x561d3c23c540), 
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2      INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 31Mb
 
ALARM: working on the last Unit for 121 seconds
       and the timeout value is 120 (use -timeout=N to change)
MS: 4 InsertByte-ChangeBinInt-InsertByte-InsertByte-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
0x32,0xa,0xa9,0x30,
2\012\2510
artifact_prefix='./'; Test unit written to ./timeout-921fccc1cbbc280da427d325cb8b9aaf1af1f4f8
Base64: MgqpMA==
==61066== ERROR: libFuzzer: timeout after 121 seconds
    #0 0x561d3c1beb15 in __sanitizer_print_stack_trace (nonSpace+0x10cb15) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #1 0x561d3c11862c in fuzzer::PrintStackTrace() (nonSpace+0x6662c) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #2 0x561d3c0fe62b in fuzzer::Fuzzer::AlarmCallback() (nonSpace+0x4c62b) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #3 0x7f15b76f531f  (/lib/x86_64-linux-gnu/libc.so.6+0x4531f) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)
    #4 0x561d3c116911 in __sanitizer_cov_trace_const_cmp8 (nonSpace+0x64911) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #5 0x561d3c1f48d1 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>::end() const /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/basic_string.h:983:41
    #6 0x561d3c1f48d1 in has_nonspace_chars(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) src/common/utility/StringHelpers.C:878:21
    #7 0x561d3c1f4ddd in LLVMFuzzerTestOneInput fuzzer.cpp:29:3
    #8 0x561d3c0ffc84 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (nonSpace+0x4dc84) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #9 0x561d3c0ff379 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (nonSpace+0x4d379) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #10 0x561d3c100b65 in fuzzer::Fuzzer::MutateAndTestOne() (nonSpace+0x4eb65) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #11 0x561d3c1016c5 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (nonSpace+0x4f6c5) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #12 0x561d3c0ee99f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (nonSpace+0x3c99f) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #13 0x561d3c119026 in main (nonSpace+0x67026) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)
    #14 0x7f15b76da1c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)
    #15 0x7f15b76da28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)
    #16 0x561d3c0e3984 in _start (nonSpace+0x31984) (BuildId: 62871dd2fe3a59e2a471cd7c34e29980a91685f3)

SUMMARY: libFuzzer: timeout

Potential fix

Updating the function to increment iter as shown below can fix the bug.

bool
has_nonspace_chars(const std::string &s)
{
    std::string::const_iterator iter = s.begin();
    while(iter != s.end())
    {
        if(!isspace(*iter))
        {
            return true;
        }
        iter++;
    }
    return false;
}
@Arpan3323
Copy link
Author

@JustinPrivitera or @markcmiller86, could you please confirm if this is indeed a bug? 😊

@JustinPrivitera
Copy link
Member

Yes this is a bug. Thank you for your report. We will look to fix this in a future release. I expect this ticket will be reviewed and scheduled at a later date as we continue to make progress on our unreviewed tickets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants