Skip to content

Commit e7072f5

Browse files
committed
feat(mdns): Add fuzzing job with AFL++
1 parent 1e30254 commit e7072f5

File tree

6 files changed

+68
-27
lines changed

6 files changed

+68
-27
lines changed

.github/workflows/mdns__host-tests.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,44 @@ jobs:
6868
diff -q $file /tmp/$file || exit 1
6969
echo "OK"
7070
done
71+
72+
73+
fuzz_test:
74+
if: contains(github.event.pull_request.labels.*.name, 'mdns-fuzz') || github.event_name == 'push'
75+
name: Fuzzer tests for mdns lib
76+
strategy:
77+
matrix:
78+
idf_ver: ["latest"]
79+
80+
runs-on: ubuntu-22.04
81+
container: aflplusplus/aflplusplus
82+
steps:
83+
- name: Checkout esp-protocols
84+
uses: actions/checkout@v4
85+
86+
- name: Checkout ESP-IDF
87+
uses: actions/checkout@v4
88+
with:
89+
repository: espressif/esp-idf
90+
path: idf
91+
submodules: recursive
92+
93+
- name: Install Necessary Libs
94+
run: |
95+
apt-get update -y
96+
apt-get install -y libbsd-dev
97+
98+
- name: Run AFL++
99+
shell: bash
100+
run: |
101+
export IDF_PATH=$GITHUB_WORKSPACE/idf
102+
cd components/mdns/tests/test_afl_fuzz_host/
103+
make fuzz
104+
105+
- name: Upload Crash Artifacts
106+
if: failure()
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: fuzz-crashes
110+
path: components/mdns/tests/test_afl_fuzz_host/out/default/crashes.tar.gz
111+
if-no-files-found: ignore

components/mdns/mdns_receive.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,11 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it
284284
}
285285

286286
int name_len = _mdns_txt_item_name_get_len(data + i, partLen);
287-
if (name_len < 0) {//invalid item (no name)
287+
if (name_len < 0 || txt_num >= num_items) { //invalid item (no name or more items than expected)
288288
i += partLen;
289289
continue;
290290
}
291-
char *key = (char *)mdns_mem_malloc(name_len + 1);
291+
char *key = (char *) mdns_mem_malloc(name_len + 1);
292292
if (!key) {
293293
HOOK_MALLOC_FAILED;
294294
goto handle_error;//error
@@ -305,7 +305,7 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it
305305

306306
int new_value_len = partLen - name_len - 1;
307307
if (new_value_len > 0) {
308-
char *value = (char *)mdns_mem_malloc(new_value_len + 1);
308+
char *value = (char *) mdns_mem_malloc(new_value_len + 1);
309309
if (!value) {
310310
HOOK_MALLOC_FAILED;
311311
goto handle_error;//error
@@ -315,6 +315,8 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it
315315
*value_len = new_value_len;
316316
i += new_value_len;
317317
t->value = value;
318+
} else {
319+
t->value = NULL;
318320
}
319321
}
320322

components/mdns/mdns_utils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,12 @@ bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instanc
202202
const char *_mdns_get_default_instance_name(void)
203203
{
204204
const char* instance = mdns_utils_get_instance();
205-
if (mdns_utils_str_null_or_empty(instance)) {
205+
if (!mdns_utils_str_null_or_empty(instance)) {
206206
return instance;
207207
}
208208

209209
const char* host = mdns_utils_get_global_hostname();
210-
if (mdns_utils_str_null_or_empty(host)) {
210+
if (!mdns_utils_str_null_or_empty(host)) {
211211
return host;
212212
}
213213
return NULL;

components/mdns/tests/test_afl_fuzz_host/Makefile

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
TEST_NAME=test
22
FUZZ=afl-fuzz
33
COMPONENTS_DIR=$(IDF_PATH)/components
4-
COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf)
4+
# Use ESP32 toolchain include path if available, otherwise fall back to system includes for host-based compilation
5+
COMPILER_INCLUDE_DIR=$(shell if command -v xtensa-esp32-elf-gcc >/dev/null 2>&1; then echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf; else echo /usr; fi)
56

67
CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ \
78
-I. -I../.. -I../../include -I../../private_include -I ./build/config \
@@ -34,7 +35,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi
3435
-I$(COMPONENTS_DIR)/soc/src/esp32/include \
3536
-I$(COMPONENTS_DIR)/xtensa/include \
3637
-I$(COMPONENTS_DIR)/xtensa/esp32/include \
37-
-I$(COMPILER_ICLUDE_DIR)/include
38+
-I$(COMPILER_INCLUDE_DIR)/include
3839

3940

4041
MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h
@@ -85,7 +86,18 @@ $(TEST_NAME): $(OBJECTS)
8586
@$(LD) $(OBJECTS) -o $@ $(LDLIBS)
8687

8788
fuzz: $(TEST_NAME)
88-
@$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME)
89+
# timeout returns 124 if time limit is reached, original return code otherwise
90+
# pass only if: fuzzing was running smoothly until timeout AND no crash found
91+
@timeout 10m $(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) || \
92+
if [ $$? -eq 124 ]; then \
93+
if [ -n "$$(find out/default/crashes -type f 2>/dev/null)" ]; then \
94+
echo "Crashes found!"; \
95+
tar -czf out/default/crashes.tar.gz -C out/default crashes; \
96+
exit 1; \
97+
fi \
98+
else \
99+
exit 1; \
100+
fi
89101

90102
clean:
91103
@rm -rf *.o *.SYM $(TEST_NAME) out

components/mdns/tests/test_afl_fuzz_host/esp32_mock.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@
5555

5656
#define pdMS_TO_TICKS(a) a
5757
#define xSemaphoreTake(s,d) true
58-
#define xTaskDelete(a)
59-
#define vTaskDelete(a) free(a)
58+
#define vTaskDelete(a) free(NULL)
6059
#define xSemaphoreGive(s)
6160
#define xQueueCreateMutex(s)
6261
#define _mdns_pcb_init(a,b) true
@@ -66,7 +65,7 @@
6665
#define vSemaphoreDelete(s) free(s)
6766
#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U
6867
#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1)
69-
#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) true
68+
#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) ((void*)1)
7069
#define vTaskDelay(m) usleep((m)*0)
7170
#define esp_random() (rand()%UINT32_MAX)
7271

components/mdns/tests/test_afl_fuzz_host/test.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,30 +81,20 @@ static int mdns_test_service_txt_set(const char *service, const char *proto, ui
8181
static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port)
8282
{
8383
if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
84-
// This is expected failure as the service thread is not running
84+
return ESP_FAIL;
8585
}
86-
mdns_action_t *a = NULL;
87-
GetLastItem(&a);
88-
mdns_test_execute_action(a);
8986

9087
if (_mdns_get_service_item(service_name, proto, NULL) == NULL) {
9188
return ESP_FAIL;
9289
}
93-
int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name);
94-
a = NULL;
95-
GetLastItem(&a);
96-
mdns_test_execute_action(a);
97-
return ret;
90+
return mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name);
9891
}
9992

10093
static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port)
10194
{
10295
if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
103-
// This is expected failure as the service thread is not running
96+
return ESP_FAIL;
10497
}
105-
mdns_action_t *a = NULL;
106-
GetLastItem(&a);
107-
mdns_test_execute_action(a);
10898

10999
if (_mdns_get_service_item(service_name, proto, NULL) == NULL) {
110100
return ESP_FAIL;
@@ -270,9 +260,6 @@ int main(int argc, char **argv)
270260
}
271261
#ifndef MDNS_NO_SERVICES
272262
mdns_service_remove_all();
273-
mdns_action_t *a = NULL;
274-
GetLastItem(&a);
275-
mdns_test_execute_action(a);
276263
#endif
277264
ForceTaskDelete();
278265
mdns_free();

0 commit comments

Comments
 (0)