Fuzzing of native http1 parser

This commit is contained in:
Olof hagsand 2022-02-08 21:26:53 +01:00
parent 4aa74fa1d8
commit 51fd973642
8 changed files with 132 additions and 6 deletions

View file

@ -279,13 +279,13 @@ absolute_paths : absolute_paths absolute_path
{
if (($$ = clixon_string_del_join($1, "/", $2)) == NULL) { free($2); YYABORT;}
free($2);
_PARSE_DEBUG("absolute-paths -> absolute-paths absolute -path");
_PARSE_DEBUG("absolute-paths -> absolute-paths absolute-path");
}
| absolute_path
{
if (($$ = clixon_string_del_join(NULL, "/", $1)) == NULL) { free($1); YYABORT;}
free($1);
_PARSE_DEBUG("absolute-paths -> absolute -path");
_PARSE_DEBUG("absolute-paths -> absolute-path");
}
;
@ -326,10 +326,12 @@ header_fields : header_fields header_field CRLF
field-name = token */
header_field : TOKEN COLON ows field_values ows
{
if (http1_parse_header_field(_HY, $1, $4) < 0)
YYABORT;
if ($4){
if (http1_parse_header_field(_HY, $1, $4) < 0)
YYABORT;
free($4);
}
free($1);
free($4);
_PARSE_DEBUG("header-field -> field-name : field-values");
}
;
@ -342,7 +344,7 @@ field_values : field_vchars
$$ = $1; // XXX is there more than one??
_PARSE_DEBUG("field-values -> field-values field-vchars");
}
| { _PARSE_DEBUG("field-values -> "); }
| { $$ = NULL; _PARSE_DEBUG("field-values -> "); }
;

View file

@ -1400,6 +1400,11 @@ usage(clicon_handle h,
exit(0);
}
/* Enable for normal use
* Disable for unit testing, fuzzing, etc
*/
#if 1
int
main(int argc,
char **argv)
@ -1602,3 +1607,42 @@ main(int argc,
restconf_terminate(h);
return retval;
}
#else /* Unit test */
int
main(int argc,
char **argv)
{
int retval = -1;
clicon_handle h = NULL;
restconf_conn *rc;
int dbg = 0;
int c;
while ((c = getopt(argc, argv, "hD:")) != -1)
switch (c) {
case 'h':
fprintf(stderr, "%s [-h] [-D <dbg>]\n", argv[0]);
break;
case 'D' : /* debug. Note this overrides any setting in the config */
if (sscanf(optarg, "%d", &dbg) != 1)
fprintf(stderr, "%s [-h] [-D <dbg>]\n", argv[0]);
break;
}
if ((h = restconf_handle_init()) == NULL)
goto done;
clicon_log_init(__FILE__, LOG_DEBUG, CLICON_LOG_STDERR);
clicon_debug_init(dbg, NULL);
if ((rc = restconf_conn_new(h, 0)) == NULL)
goto done;
if (restconf_stream_data_new(rc, 0) == NULL)
goto done;
if (clixon_http1_parse_file(h, rc, stdin, "stdin") < 0)
goto done;
retval = 0;
done:
return retval;
}
#endif

28
test/fuzz/http1/README.md Normal file
View file

@ -0,0 +1,28 @@
# Clixon http1 fuzzing
This dir contains code for fuzzing the clixon http1 parser. This is normally inside the
native restconf app and need some special compiling to run stand-alone.
Install AFL, see [..](..)
Edit `apps/restconf/restconf_main_native.c` by disabling the regular
main function and replacing it with the unit testing `main`:
```
--- a/apps/restconf/restconf_main_native.c
+++ b/apps/restconf/restconf_main_native.c
@@ -1403,7 +1403,7 @@ usage(clicon_handle h,
/* Enable for normal use
* Disable for unit testing, fuzzing, etc
*/
-#if 1
+#if 0
```
Build and install clixon libraries and restconf statically
```
./configure LINKAGE=static INSTALLFLAGS="" CC=/usr/bin/afl-clang-fast
make
sudo make install
./runfuzz.sh
```

View file

@ -0,0 +1,10 @@
PUT /restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0 HTTP/1.1
Host: 127.0.0.1
Accept: */*
Content-Type: application/yang-data+json
Content-Length: 91
{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}

View file

@ -0,0 +1,5 @@
GET /restconf/data HTTP/1.1
Host: localhost
Accept: application/yang-data+xml

View file

@ -0,0 +1,8 @@
POST /restconf/data/ietf-interfaces:interfaces HTTP/1.1
Host: 127.0.0.1
Accept: application/yang-data+xml
Content-Type: application/yang-data+xml
Content-Length: 138
<interface xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"><name>eth/0/42</name><type>ex:eth</type><enabled>true</enabled></interface>

View file

@ -0,0 +1,4 @@
DELETE /restconf/data/ietf-interfaces:interfaces HTTP/1.1
Host: 127.0.0.1

25
test/fuzz/http1/runfuzz.sh Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Run a fuzzing test using american fuzzy lop
# Add input strings in input
set -eux
if [ $# -ne 0 ]; then
echo "usage: $0"
exit 255
fi
MEGS=500 # memory limit for child process (50 MB)
# remove input and input dirs
#test ! -d input || rm -rf input
test ! -d output || sudo rm -rf output
# create if dirs dont exists
#test -d input || mkdir input
test -d output || mkdir output
# Run script
# CC=/usr/bin/afl-clang
sudo afl-fuzz -i input -o output -d -m $MEGS -- /usr/local/sbin/clixon_restconf