mirror of
https://github.com/yshui/picom.git
synced 2024-10-27 05:24:17 -04:00
c2: add a libfuzzer fuzzer for c2
Add fix some simple bugs discovered by the fuzzer. Two cases of missing input validation (we have assertions, but assertion failures are not user friendly). And one case of jump over variable initialization with goto. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
04e7306cfa
commit
c23dbe61f7
3 changed files with 69 additions and 7 deletions
46
src/c2.c
46
src/c2.c
|
@ -479,6 +479,27 @@ TEST_CASE(c2_parse) {
|
||||||
|
|
||||||
cond = c2_parse(NULL, "_NET_WM_STATE = '_NET_WM_STATE_HIDDEN'", NULL);
|
cond = c2_parse(NULL, "_NET_WM_STATE = '_NET_WM_STATE_HIDDEN'", NULL);
|
||||||
TEST_EQUAL(cond, NULL);
|
TEST_EQUAL(cond, NULL);
|
||||||
|
|
||||||
|
cond = c2_parse(NULL, "1A:\n1111111111111ar1", NULL);
|
||||||
|
TEST_EQUAL(cond, NULL);
|
||||||
|
|
||||||
|
cond = c2_parse(NULL, "N [4444444444444: \n", NULL);
|
||||||
|
TEST_EQUAL(cond, NULL);
|
||||||
|
|
||||||
|
cond = c2_parse(NULL, " x:a=\"b\377\\xCCCCC", NULL);
|
||||||
|
TEST_EQUAL(cond, NULL);
|
||||||
|
|
||||||
|
cond = c2_parse(NULL, "!!!!!!!((((((!(((((,", NULL);
|
||||||
|
TEST_EQUAL(cond, NULL);
|
||||||
|
|
||||||
|
const char *rule = "(((role:s = \"\\\\tg^\\n\\n[\\t\" && role:s ~?= \"\") && "
|
||||||
|
"role:s ~?= \"\\n\\n\\n\\b\\n^\\n*0bon\") && role:s ~?= "
|
||||||
|
"\"\\n\\n\\x8a\\b\\n^\\n*0\\n[\\n[\\n\\n\\b\\n\")";
|
||||||
|
cond = c2_parse(NULL, rule, NULL);
|
||||||
|
TEST_NOTEQUAL(cond, NULL);
|
||||||
|
len = c2_condition_to_str(cond->ptr, str, sizeof(str));
|
||||||
|
TEST_STREQUAL3(str, rule, len);
|
||||||
|
c2_list_free(&cond, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define c2_error(format, ...) \
|
#define c2_error(format, ...) \
|
||||||
|
@ -500,11 +521,6 @@ TEST_CASE(c2_parse) {
|
||||||
* @return offset of next character in string
|
* @return offset of next character in string
|
||||||
*/
|
*/
|
||||||
static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
|
static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
|
||||||
// Check for recursion levels
|
|
||||||
if (level > C2_MAX_LEVELS) {
|
|
||||||
c2_error("Exceeded maximum recursion levels.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -531,6 +547,11 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
|
||||||
// after encountering a logical operator
|
// after encountering a logical operator
|
||||||
bool next_expected = true;
|
bool next_expected = true;
|
||||||
|
|
||||||
|
// Check for recursion levels
|
||||||
|
if (level > C2_MAX_LEVELS) {
|
||||||
|
c2_error("Exceeded maximum recursion levels.");
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the pattern character-by-character
|
// Parse the pattern character-by-character
|
||||||
for (; pattern[offset]; ++offset) {
|
for (; pattern[offset]; ++offset) {
|
||||||
assert(elei <= 2);
|
assert(elei <= 2);
|
||||||
|
@ -753,8 +774,11 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
if (!endptr || pattern + offset == endptr) {
|
if (!endptr || pattern + offset == endptr) {
|
||||||
c2_error("No index number found after bracket.");
|
c2_error("No index number found after bracket.");
|
||||||
}
|
}
|
||||||
|
if (index > INT_MAX) {
|
||||||
|
c2_error("Index %ld too large.", index);
|
||||||
|
}
|
||||||
|
|
||||||
pleaf->index = to_int_checked(index);
|
pleaf->index = (int)index;
|
||||||
offset = to_int_checked(endptr - pattern);
|
offset = to_int_checked(endptr - pattern);
|
||||||
|
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
|
@ -989,7 +1013,15 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
|
||||||
c2_error("Invalid octal/hex escape "
|
c2_error("Invalid octal/hex escape "
|
||||||
"sequence.");
|
"sequence.");
|
||||||
}
|
}
|
||||||
*(ptptnstr++) = to_char_checked(val);
|
if (val > 255) {
|
||||||
|
c2_error("Octal/hex escape sequence out "
|
||||||
|
"of ASCII range.");
|
||||||
|
}
|
||||||
|
if (val > 127) {
|
||||||
|
// Manual sign extension
|
||||||
|
val -= 256;
|
||||||
|
}
|
||||||
|
*(ptptnstr++) = (char)val;
|
||||||
offset += 2;
|
offset += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
20
src/fuzzer/c2.c
Normal file
20
src/fuzzer/c2.c
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#include "c2.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
|
log_init_tls();
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (data[size - 1] != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
c2_lptr_t *cond = c2_parse(NULL, (char *)data, NULL);
|
||||||
|
(void)cond;
|
||||||
|
(void)size;
|
||||||
|
return 0; // Values other than 0 and -1 are reserved for future use.
|
||||||
|
}
|
|
@ -95,3 +95,13 @@ picom = executable('picom', srcs, c_args: cflags,
|
||||||
if get_option('unittest')
|
if get_option('unittest')
|
||||||
test('picom unittest', picom, args: [ '--unittest' ])
|
test('picom unittest', picom, args: [ '--unittest' ])
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if cc.has_argument('-fsanitize=fuzzer')
|
||||||
|
c2_fuzz = executable('c2_fuzz', srcs + ['fuzzer/c2.c'],
|
||||||
|
c_args: cflags + ['-fsanitize=fuzzer', '-Dmain=__main__'],
|
||||||
|
link_args: ['-fsanitize=fuzzer'],
|
||||||
|
dependencies: [ base_deps, deps, test_h_dep ],
|
||||||
|
build_by_default: false,
|
||||||
|
install: false, include_directories: picom_inc
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
Loading…
Reference in a new issue