Permalink
Browse files

Added fuzzing and fixed some minor non-security-related crashers.

Also added ABNF, for reference and for use by abnfgen for fuzzing.
  • Loading branch information...
1 parent a0cf064 commit 27ba5d5f17ca122f96a378a800074891a285207a @darconeous committed Feb 1, 2012
Showing with 132 additions and 28 deletions.
  1. +5 −0 .gitignore
  2. +5 −0 Makefile
  3. +23 −25 assert-macros.h
  4. +23 −0 freq-uri-abnf.txt
  5. +38 −0 freq-uri-query-abnf.txt
  6. +22 −1 freq-uri.c
  7. +14 −0 fuzz.sh
  8. +2 −2 main.c
View
@@ -0,0 +1,5 @@
+/freq-parser
+/freq-uri.o
+/main.o
+/url-helpers.o
+
View
@@ -26,6 +26,8 @@
# * <http://creativecommons.org/publicdomain/zero/1.0/>
#
+CFLAGS:=-g -O0 -DDEBUG=1
+
freq-parser: main.o freq-uri.o url-helpers.o
$(CC) -o $@ $^
@@ -40,6 +42,9 @@ test: freq-parser
@./freq-parser 'x-freq:2.6?m=cw'
@./freq-parser 'x-freq:441.3m+5?m=fm;dv=2.5;ts=100/123.0'
+fuzz: freq-parser
+ ./fuzz.sh
+
main.o: main.c freq-uri.h
url-helpers.o: url-helpers.c url-helpers.h assert-macros.h
freq-uri.o: freq-uri.c freq-uri.h assert-macros.h
View
@@ -29,6 +29,12 @@
** * <http://creativecommons.org/publicdomain/zero/1.0/>
**
** See <http://www.deepdarc.com/> for other cool stuff.
+**
+** -------------------------------------------------------------------
+**
+** See <http://www.mactech.com/articles/develop/issue_11/Parent_final.html>
+** for an explanation about how to use these macros and justification
+** for using this pattern in general.
*/
#ifndef __DARC_ASSERT_MACROS__
@@ -46,6 +52,7 @@
#include <stdio.h>
#include <assert.h>
#if !DEBUG
+ #define assert_printf(fmt, ...) do { } while(0)
#define check_string(c, s) do { } while(0)
#define require_action_string(c, l, a, s) \
do { if(!(c)) { \
@@ -54,36 +61,27 @@
} while(0)
#else
#if __AVR__
- #define check_string(c, s) \
- do { if(!(c)) fprintf_P(assert_error_stream, \
- PSTR(__FILE__ ":%d: Check Failed (%s)\n"), \
- __LINE__, \
- s); } while(0)
- #define require_action_string(c, l, a, s) \
- do { if(!(c)) { \
- fprintf_P( \
- assert_error_stream, \
- PSTR(__FILE__ ":%d: Assert Failed (%s)\n"), \
+ #define assert_printf(fmt, ...) \
+ fprintf_P(assert_error_stream, \
+ PSTR(__FILE__ ":%d: "fmt"\n"), \
__LINE__, \
- s); a; goto l; \
- } \
- } while(0)
+ __VA_ARGS__)
#else
- #define check_string(c, s) \
- do { if(!(c)) fprintf(assert_error_stream, \
- __FILE__ ":%d: Check Failed (%s)\n", \
+ #define assert_printf(fmt, ...) \
+ fprintf(assert_error_stream, \
+ __FILE__ ":%d: "fmt"\n", \
__LINE__, \
- s); } while(0)
- #define require_action_string(c, l, a, s) \
- do { if(!(c)) { \
- fprintf( \
- assert_error_stream, \
- __FILE__ ":%d: Assert Failed (%s)\n", \
- __LINE__, \
- s); a; goto l; \
+ __VA_ARGS__)
+ #endif
+ #define check_string(c, s) \
+ do { if(!(c)) assert_printf("Check Failed (%s)", \
+ s); } while(0)
+ #define require_action_string(c, l, a, s) \
+ do { if(!(c)) { \
+ assert_printf("Requirement Failed (%s)", \
+ s); a; goto l; \
} \
} while(0)
- #endif
#endif
#define check(c) check_string(c, # c)
View
@@ -0,0 +1,23 @@
+frequri = 'x-freq:' freqcomp [ '?' querycomp ]
+freqcomp = freq [ shift / tx-freq ]
+freq = float [ unit ]
+shift = ( "+" / "-" ) freq
+tx-freq = "/" freq
+float = 1*DIGIT [ "." *DIGIT ] / "." 1*DIGIT
+unit = 'h' ['z'] / 'k' ['hz'] / 'm' ['hz'] / 'g' ['hz'] / 't' ['hz']
+querycomp = pair *( ";" pair )
+pair = key "=" value
+key = keyfirst *( keychar )
+keyfirst = ( ALPHA / '_' / ':' )
+keychar = ( keyfirst / DIGIT / '-' / '.' )
+value = *( unreserved / pct-encoded ) [ '/' *( unreserved / pct-encoded ) ]
+
+; The following rules come from the related URI RFC.
+
+reserved = gen-delims / sub-delims
+gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
+unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+pct-encoded = "%" HEXDIG HEXDIG
+;pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+;fragment = *( pchar / "/" / "?" )
View
@@ -0,0 +1,38 @@
+; Used primarily for fuzzing, but may also be useful to
+; people who want to see exactly how the proposed query
+; components are described.
+
+frequri = 'x-freq:' freqcomp [ '?' querycomp ]
+freqcomp = freq [ shift / tx-freq ]
+freq = float [ unit ]
+shift = ( "+" / "-" ) freq
+tx-freq = "/" freq
+float = 1*DIGIT [ "." *DIGIT ] / "." 1*DIGIT
+unit = 'h' ['z'] / 'k' ['hz'] / 'm' ['hz'] / 'g' ['hz'] / 't' ['hz']
+querycomp = pair *( ";" pair )
+;pair = key "=" value
+;key = keyfirst *( keychar )
+;keyfirst = ( ALPHA / '_' / ':' )
+;keychar = ( keyfirst / DIGIT / '-' / '.' )
+value = *( unreserved / pct-encoded ) [ '/' *( unreserved / pct-encoded ) ]
+pair = m-pair / bw-pair / dv-pair / ts-pair / dcs-pair / std-pair / tp-pair
+m-value = ( 'am' / 'fm' / 'sb' / 'cw' )
+m-pair = 'm=' m-value [ '/' m-value ]
+bw-value = freq [ ':' freq ]
+bw-pair = 'bw=' bw-value [ '/' bw-value ]
+dv-pair = 'dv=' freq [ '/' freq ]
+ts-pair = 'ts=' float [ '/' float ]
+dcs-pair = 'dcs=' 1*DIGIT [ '/' 1*DIGIT ]
+std-pair = 'std=' value
+tp-pair = 'tp=' float [ '/' float ]
+
+
+; The following rules come from the related URI RFC.
+
+reserved = gen-delims / sub-delims
+gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
+unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+pct-encoded = "%" HEXDIG HEXDIG
+;pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+;fragment = *( pchar / "/" / "?" )
View
@@ -63,7 +63,7 @@ unitmultiplier(char unit) {
case 'm': fmult=1000000.0; break;
case 'g': fmult=1000000000.0; break;
case 't': fmult=1000000000000.0; break;
- default: printf("Bad mult char: [%c] (%d)\n",unit,unit); break;
+ default: assert_printf("Bad mult char: [%c] (%d)\n",unit,unit); break;
}
return fmult;
}
@@ -88,6 +88,11 @@ strtofreq(const char * nptr, char ** endptr, char* multchar) {
if(multchar)
*multchar = tolower(ep[0]);
ep++;
+
+ // Skip optional 'hz' suffix if present.
+ if( ('h'==tolower(ep[0]))
+ && ('z'==tolower(ep[1]))
+ ) ep += 2;
}
}
@@ -99,6 +104,12 @@ strtofreq(const char * nptr, char ** endptr, char* multchar) {
static void
parse_query_param(freq_t* freq,const char* key,const char* value) {
+
+ assert(freq!=NULL);
+
+ require(value!=NULL,bail);
+ require(key!=NULL,bail);
+
if(0==strcmp(key,"m")) {
// Parse Modulation.
if(0==strcmp(value,"am")) {
@@ -155,15 +166,22 @@ parse_query_param(freq_t* freq,const char* key,const char* value) {
// Ignore unknown query keys.
}
+bail:
+ return;
}
static void
split_and_decode(char* value, char** value_rx, char** value_tx) {
int i;
+ assert(value_rx!=NULL);
+ assert(value_tx!=NULL);
+
*value_rx = value;
*value_tx = value;
+ require(value!=NULL,bail);
+
for(i=0;value[i];i++) {
if(value[i]=='/') {
// Zero-terminate at the seperator.
@@ -175,6 +193,9 @@ split_and_decode(char* value, char** value_rx, char** value_tx) {
}
}
url_decode_cstr_inplace(*value_rx);
+
+bail:
+ return;
}
int
View
14 fuzz.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+which abnfgen 1>/dev/null || { echo Missing abnfgen. ; exit 1 ; }
+
+for ((i=0;i<100000;i++))
+do
+ URI=`abnfgen -c freq-uri-abnf.txt`
+ echo Testing '<'$URI'>'
+ ./freq-parser $URI > /dev/null || exit -1
+
+ URI=`abnfgen -c freq-uri-query-abnf.txt`
+ echo Testing '<'$URI'>'
+ ./freq-parser $URI > /dev/null || exit -1
+done
View
4 main.c
@@ -35,8 +35,8 @@
void
parse_and_print(const char* uri) {
- freq_t rx_freq = {};
- freq_t tx_freq = {};
+ freq_t rx_freq = { 0 };
+ freq_t tx_freq = { 0 };
freq_parse_uri(uri,0,&rx_freq,&tx_freq);

0 comments on commit 27ba5d5

Please sign in to comment.