Skip to content

Commit fa146ab

Browse files
committed
fix(mdns): Add fuzzing into mdns CI
1 parent 6f6237a commit fa146ab

File tree

4 files changed

+74
-29
lines changed

4 files changed

+74
-29
lines changed

.github/workflows/mdns__host-tests.yml

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

components/mdns/tests/test_afl_fuzz_host/Makefile

Lines changed: 15 additions & 4 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,8 +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$(COMPONENTS_DIR)/esp_hw_support/etm/include \
38-
-I$(COMPILER_ICLUDE_DIR)/include
38+
-I$(COMPILER_INCLUDE_DIR)/include
3939

4040

4141
MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h
@@ -77,7 +77,18 @@ $(TEST_NAME): $(OBJECTS)
7777
@$(LD) $(OBJECTS) -o $@ $(LDLIBS)
7878

7979
fuzz: $(TEST_NAME)
80-
@$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME)
80+
# timeout returns 124 if time limit is reached, original return code otherwise
81+
# pass only if: fuzzing was running smoothly until timeout AND no crash found
82+
@timeout 10m $(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) || \
83+
if [ $$? -eq 124 ]; then \
84+
if [ -n "$$(find out/default/crashes -type f 2>/dev/null)" ]; then \
85+
echo "Crashes found!"; \
86+
tar -czf out/default/crashes.tar.gz -C out/default crashes; \
87+
exit 1; \
88+
fi \
89+
else \
90+
exit 1; \
91+
fi
8192

8293
clean:
8394
@rm -rf *.o *.SYM $(TEST_NAME) out

components/mdns/tests/test_afl_fuzz_host/esp32_mock.h

Lines changed: 6 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

@@ -139,4 +138,8 @@ TaskHandle_t xTaskGetCurrentTaskHandle(void);
139138
void xTaskNotifyGive(TaskHandle_t task);
140139
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time);
141140

141+
static inline void xTaskGetStaticBuffers(void *pvTaskBuffer, void *pvStackBuffer, void *pvTaskTCB)
142+
{
143+
}
144+
142145
#endif //_ESP32_COMPAT_H_

components/mdns/tests/test_afl_fuzz_host/test.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -13,6 +13,8 @@
1313
#include "esp32_mock.h"
1414
#include "mdns.h"
1515
#include "mdns_private.h"
16+
#include "mdns_utils.h"
17+
#include "mdns_querier.h"
1618

1719
//
1820
// Global stuctures containing packet payload, search
@@ -23,20 +25,21 @@ mdns_search_once_t *search = NULL;
2325
//
2426
// Dependency injected test functions
2527
void mdns_test_execute_action(void *action);
26-
mdns_srv_item_t *mdns_test_mdns_get_service_item(const char *service, const char *proto);
2728
mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results);
2829
esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search);
2930
void mdns_test_search_free(mdns_search_once_t *search);
31+
3032
void mdns_test_init_di(void);
33+
void mdns_querier_test_init_di(void);
3134
extern mdns_server_t *_mdns_server;
3235

3336
//
3437
// mdns function wrappers for mdns setup in test mode
3538
static int mdns_test_hostname_set(const char *mdns_hostname)
3639
{
3740
for (int i = 0; i < MDNS_MAX_INTERFACES; i++) {
38-
_mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode
39-
_mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING;
41+
// _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode
42+
// _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING;
4043
}
4144
int ret = mdns_hostname_set(mdns_hostname);
4245
mdns_action_t *a = NULL;
@@ -78,32 +81,22 @@ static int mdns_test_service_txt_set(const char *service, const char *proto, ui
7881
static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port)
7982
{
8083
if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
81-
// This is expected failure as the service thread is not running
84+
return ESP_FAIL;
8285
}
83-
mdns_action_t *a = NULL;
84-
GetLastItem(&a);
85-
mdns_test_execute_action(a);
8686

87-
if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) {
87+
if (_mdns_get_service_item(service_name, proto, NULL) == NULL) {
8888
return ESP_FAIL;
8989
}
90-
int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name);
91-
a = NULL;
92-
GetLastItem(&a);
93-
mdns_test_execute_action(a);
94-
return ret;
90+
return mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name);
9591
}
9692

9793
static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port)
9894
{
9995
if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
100-
// This is expected failure as the service thread is not running
96+
return ESP_FAIL;
10197
}
102-
mdns_action_t *a = NULL;
103-
GetLastItem(&a);
104-
mdns_test_execute_action(a);
10598

106-
if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) {
99+
if (_mdns_get_service_item(service_name, proto, NULL) == NULL) {
107100
return ESP_FAIL;
108101
}
109102
return ESP_OK;
@@ -161,6 +154,7 @@ int main(int argc, char **argv)
161154

162155
// Init depencency injected methods
163156
mdns_test_init_di();
157+
mdns_querier_test_init_di();
164158

165159
if (mdns_init()) {
166160
abort();
@@ -266,9 +260,6 @@ int main(int argc, char **argv)
266260
}
267261
#ifndef MDNS_NO_SERVICES
268262
mdns_service_remove_all();
269-
mdns_action_t *a = NULL;
270-
GetLastItem(&a);
271-
mdns_test_execute_action(a);
272263
#endif
273264
ForceTaskDelete();
274265
mdns_free();

0 commit comments

Comments
 (0)