fix(mdns): Add fuzzing into mdns CI

This commit is contained in:
David Cermak
2025-10-02 12:46:44 +02:00
parent f5e62e83e9
commit af6bb1b5ee
4 changed files with 65 additions and 22 deletions

View File

@@ -68,3 +68,43 @@ jobs:
diff -q $file /tmp/$file || exit 1 diff -q $file /tmp/$file || exit 1
echo "OK" echo "OK"
done done
fuzz_test:
if: contains(github.event.pull_request.labels.*.name, 'mdns-fuzz') || github.event_name == 'push'
name: Fuzzer tests for mdns lib
strategy:
matrix:
idf_ver: ["latest"]
runs-on: ubuntu-22.04
container: aflplusplus/aflplusplus
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
- name: Checkout ESP-IDF
uses: actions/checkout@v4
with:
repository: espressif/esp-idf
path: idf
submodules: recursive
- name: Install Necessary Libs
run: |
apt-get update -y
apt-get install -y libbsd-dev
- name: Run AFL++
shell: bash
run: |
export IDF_PATH=$GITHUB_WORKSPACE/idf
cd components/mdns/tests/test_afl_fuzz_host/
make fuzz
- name: Upload Crash Artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: fuzz-crashes
path: components/mdns/tests/test_afl_fuzz_host/out/default/crashes.tar.gz
if-no-files-found: ignore

View File

@@ -1,7 +1,9 @@
#INSTR=off
TEST_NAME=test TEST_NAME=test
FUZZ=afl-fuzz FUZZ=afl-fuzz
COMPONENTS_DIR=$(IDF_PATH)/components COMPONENTS_DIR=$(IDF_PATH)/components
COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) # Use ESP32 toolchain include path if available, otherwise fall back to system includes for host-based compilation
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)
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__ \ 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__ \
-I. -I../.. -I../../include -I../../private_include -I ./build/config \ -I. -I../.. -I../../include -I../../private_include -I ./build/config \
@@ -35,7 +37,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi
-I$(COMPONENTS_DIR)/xtensa/include \ -I$(COMPONENTS_DIR)/xtensa/include \
-I$(COMPONENTS_DIR)/xtensa/esp32/include \ -I$(COMPONENTS_DIR)/xtensa/esp32/include \
-I$(COMPONENTS_DIR)/esp_hw_support/etm/include \ -I$(COMPONENTS_DIR)/esp_hw_support/etm/include \
-I$(COMPILER_ICLUDE_DIR)/include -I$(COMPILER_INCLUDE_DIR)/include
MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h
@@ -77,7 +79,18 @@ $(TEST_NAME): $(OBJECTS)
@$(LD) $(OBJECTS) -o $@ $(LDLIBS) @$(LD) $(OBJECTS) -o $@ $(LDLIBS)
fuzz: $(TEST_NAME) fuzz: $(TEST_NAME)
@$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) # timeout returns 124 if time limit is reached, original return code otherwise
# pass only if: fuzzing was running smoothly until timeout AND no crash found
@timeout 10m $(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) || \
if [ $$? -eq 124 ]; then \
if [ -n "$$(find out/default/crashes -type f 2>/dev/null)" ]; then \
echo "Crashes found!"; \
tar -czf out/default/crashes.tar.gz -C out/default crashes; \
exit 1; \
fi \
else \
exit 1; \
fi
clean: clean:
@rm -rf *.o *.SYM $(TEST_NAME) out @rm -rf *.o *.SYM $(TEST_NAME) out

View File

@@ -55,8 +55,7 @@
#define pdMS_TO_TICKS(a) a #define pdMS_TO_TICKS(a) a
#define xSemaphoreTake(s,d) true #define xSemaphoreTake(s,d) true
#define xTaskDelete(a) #define vTaskDelete(a) free(NULL)
#define vTaskDelete(a) free(a)
#define xSemaphoreGive(s) #define xSemaphoreGive(s)
#define xQueueCreateMutex(s) #define xQueueCreateMutex(s)
#define _mdns_pcb_init(a,b) true #define _mdns_pcb_init(a,b) true
@@ -66,7 +65,7 @@
#define vSemaphoreDelete(s) free(s) #define vSemaphoreDelete(s) free(s)
#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U #define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U
#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) #define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1)
#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) true #define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) ((void*)1)
#define vTaskDelay(m) usleep((m)*0) #define vTaskDelay(m) usleep((m)*0)
#define esp_random() (rand()%UINT32_MAX) #define esp_random() (rand()%UINT32_MAX)
@@ -139,4 +138,8 @@ TaskHandle_t xTaskGetCurrentTaskHandle(void);
void xTaskNotifyGive(TaskHandle_t task); void xTaskNotifyGive(TaskHandle_t task);
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time); BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time);
static inline void xTaskGetStaticBuffers(void *pvTaskBuffer, void *pvStackBuffer, void *pvTaskTCB)
{
}
#endif //_ESP32_COMPAT_H_ #endif //_ESP32_COMPAT_H_

View File

@@ -78,30 +78,20 @@ static int mdns_test_service_txt_set(const char *service, const char *proto, ui
static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port) static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port)
{ {
if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
// This is expected failure as the service thread is not running return ESP_FAIL;
} }
mdns_action_t *a = NULL;
GetLastItem(&a);
mdns_test_execute_action(a);
if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) { if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) {
return ESP_FAIL; return ESP_FAIL;
} }
int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); return mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name);
a = NULL;
GetLastItem(&a);
mdns_test_execute_action(a);
return ret;
} }
static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port) static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port)
{ {
if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
// This is expected failure as the service thread is not running return ESP_FAIL;
} }
mdns_action_t *a = NULL;
GetLastItem(&a);
mdns_test_execute_action(a);
if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) { if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) {
return ESP_FAIL; return ESP_FAIL;
@@ -266,9 +256,6 @@ int main(int argc, char **argv)
} }
#ifndef MDNS_NO_SERVICES #ifndef MDNS_NO_SERVICES
mdns_service_remove_all(); mdns_service_remove_all();
mdns_action_t *a = NULL;
GetLastItem(&a);
mdns_test_execute_action(a);
#endif #endif
ForceTaskDelete(); ForceTaskDelete();
mdns_free(); mdns_free();