For improved QA etc.
Signed-off-by: Petr Štetiar <ynezz@true.cz>
find_library(json NAMES json-c json)
+MACRO(ADD_UNIT_TEST_SAN name output_name)
+ ADD_EXECUTABLE(${name}-san ${name}.c)
+ TARGET_COMPILE_OPTIONS(${name}-san PRIVATE -g -fno-omit-frame-pointer -fsanitize=undefined,address,leak -fno-sanitize-recover=all)
+ TARGET_LINK_OPTIONS(${name}-san PRIVATE -fsanitize=undefined,address,leak)
+ TARGET_LINK_LIBRARIES(${name}-san ubus ubusd_library ${ubox_library} ${blob_library} ${json})
+ TARGET_INCLUDE_DIRECTORIES(${name}-san PRIVATE ${PROJECT_SOURCE_DIR})
+ SET_TARGET_PROPERTIES(${name}-san PROPERTIES OUTPUT_NAME ${output_name})
+ENDMACRO(ADD_UNIT_TEST_SAN)
+
ADD_LIBRARY(ubusd_library STATIC ubusd.c ubusd_proto.c ubusd_id.c ubusd_obj.c ubusd_event.c ubusd_acl.c ubusd_monitor.c)
ADD_EXECUTABLE(ubusd ubusd_main.c)
TARGET_LINK_LIBRARIES(ubusd ubusd_library ${ubox_library} ${blob_library} ${json})
ADD_SUBDIRECTORY(lua)
ADD_SUBDIRECTORY(examples)
+IF(UNIT_TESTING)
+ ENABLE_TESTING()
+ ADD_SUBDIRECTORY(tests)
+ ADD_UNIT_TEST_SAN(cli ubus-san)
+ ADD_UNIT_TEST_SAN(ubusd_main ubusd-san)
+ENDIF()
+
INSTALL(TARGETS ubus cli
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
--- /dev/null
+ADD_SUBDIRECTORY(cram)
+
+MACRO(ADD_UNIT_TEST name)
+ ADD_EXECUTABLE(${name} ${name}.c)
+ TARGET_LINK_LIBRARIES(${name} ubox blobmsg_json json_script ${json})
+ TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+ENDMACRO(ADD_UNIT_TEST)
+
+FILE(GLOB test_cases "test-*.c")
+FOREACH(test_case ${test_cases})
+ GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+ ADD_UNIT_TEST(${test_case})
+ ADD_UNIT_TEST_SAN(${test_case})
+ENDFOREACH(test_case)
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_SUBDIRECTORY(fuzz)
+ENDIF()
--- /dev/null
+FIND_PACKAGE(PythonInterp 3 REQUIRED)
+FILE(GLOB test_cases "test_*.t")
+
+SET(PYTHON_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/.venv")
+SET(PYTHON_VENV_PIP "${PYTHON_VENV_DIR}/bin/pip")
+SET(PYTHON_VENV_CRAM "${PYTHON_VENV_DIR}/bin/cram")
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${PYTHON_VENV_CRAM}
+ COMMAND ${PYTHON_EXECUTABLE} -m venv ${PYTHON_VENV_DIR}
+ COMMAND ${PYTHON_VENV_PIP} install cram
+)
+ADD_CUSTOM_TARGET(prepare-cram-venv ALL DEPENDS ${PYTHON_VENV_CRAM})
+
+ADD_TEST(
+ NAME cram
+ COMMAND ${PYTHON_VENV_CRAM} ${test_cases}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "UBUS=$<TARGET_FILE:ubus>")
+SET_PROPERTY(TEST cram APPEND PROPERTY ENVIRONMENT "TEST_BIN_DIR=$<TARGET_FILE_DIR:ubus>")
--- /dev/null
+set environment for convenience:
+
+ $ [ -n "$TEST_BIN_DIR" ] && export PATH="$TEST_BIN_DIR:$PATH"
+ $ alias ubus='valgrind --quiet --leak-check=full ubus'
+
+check usage:
+
+ $ ubus
+ Usage: ubus [<options>] <command> [arguments...]
+ Options:
+ -s <socket>:\t\tSet the unix domain socket to connect to (esc)
+ -t <timeout>:\t\tSet the timeout (in seconds) for a command to complete (esc)
+ -S:\t\t\tUse simplified output (for scripts) (esc)
+ -v:\t\t\tMore verbose output (esc)
+ -m <type>:\t\t(for monitor): include a specific message type (esc)
+ \t\t\t(can be used more than once) (esc)
+ -M <r|t>\t\t(for monitor): only capture received or transmitted traffic (esc)
+
+ Commands:
+ - list [<path>]\t\t\tList objects (esc)
+ - call <path> <method> [<message>]\tCall an object method (esc)
+ - listen [<path>...]\t\t\tListen for events (esc)
+ - send <type> [<message>]\t\tSend an event (esc)
+ - wait_for <object> [<object>...]\tWait for multiple objects to appear on ubus (esc)
+ - monitor\t\t\t\tMonitor ubus traffic (esc)
+
+ [1]
+
+ $ ubus-san
+ Usage: ubus-san [<options>] <command> [arguments...]
+ Options:
+ -s <socket>:\t\tSet the unix domain socket to connect to (esc)
+ -t <timeout>:\t\tSet the timeout (in seconds) for a command to complete (esc)
+ -S:\t\t\tUse simplified output (for scripts) (esc)
+ -v:\t\t\tMore verbose output (esc)
+ -m <type>:\t\t(for monitor): include a specific message type (esc)
+ \t\t\t(can be used more than once) (esc)
+ -M <r|t>\t\t(for monitor): only capture received or transmitted traffic (esc)
+
+ Commands:
+ - list [<path>]\t\t\tList objects (esc)
+ - call <path> <method> [<message>]\tCall an object method (esc)
+ - listen [<path>...]\t\t\tListen for events (esc)
+ - send <type> [<message>]\t\tSend an event (esc)
+ - wait_for <object> [<object>...]\tWait for multiple objects to appear on ubus (esc)
+ - monitor\t\t\t\tMonitor ubus traffic (esc)
+
+ [1]
+
+check monitor command:
+
+ $ ubus monitor
+ Failed to connect to ubus
+ [255]
+
+ $ ubus-san monitor
+ Failed to connect to ubus
+ [255]
--- /dev/null
+set environment for convenience:
+
+ $ [ -n "$TEST_BIN_DIR" ] && export PATH="$TEST_BIN_DIR:$PATH"
+ $ alias ubusd='valgrind --quiet --leak-check=full ubusd'
+
+check usage:
+
+ $ ubusd -h
+ ubusd: invalid option -- 'h'
+ Usage: ubusd [<options>]
+ Options:
+ -A <path>:\t\tSet the path to ACL files (esc)
+ -s <socket>:\t\tSet the unix domain socket to listen on (esc)
+
+ [1]
+
+ $ ubusd-san -h
+ ubusd-san: invalid option -- 'h'
+ Usage: ubusd-san [<options>]
+ Options:
+ -A <path>:\t\tSet the path to ACL files (esc)
+ -s <socket>:\t\tSet the unix domain socket to listen on (esc)
+
+ [1]
--- /dev/null
+FILE(GLOB test_cases "test-*.c")
+
+MACRO(ADD_FUZZER_TEST name)
+ ADD_EXECUTABLE(${name} ${name}.c)
+ TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
+ TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+ TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
+ TARGET_LINK_LIBRARIES(${name} ubus ubusd_library ${ubox_library} ${blob_library} ${json})
+ ADD_TEST(
+ NAME ${name}
+ COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
+ )
+ENDMACRO(ADD_FUZZER_TEST)
+
+FOREACH(test_case ${test_cases})
+ GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+ ADD_FUZZER_TEST(${test_case})
+ENDFOREACH(test_case)
--- /dev/null
+6
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
+
+#include <libubox/blob.h>
+#include <libubox/blobmsg.h>
+
+#include "ubusmsg.h"
+#include "libubus.h"
+#include "libubus-internal.h"
+
+static void _ubus_validate_hdr(const uint8_t *data, size_t size)
+{
+ if (size > sizeof(struct ubus_msghdr))
+ return;
+
+ ubus_validate_hdr((struct ubus_msghdr *) data);
+}
+
+static void _ubus_parse_msg(const uint8_t *data, size_t size)
+{
+ struct blob_attr *attr = (struct blob_attr *) data;
+
+ if (size < sizeof(struct blob_attr *))
+ return;
+
+ if (blob_pad_len(attr) > UBUS_MAX_MSGLEN)
+ return;
+
+ ubus_parse_msg(attr);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ _ubus_validate_hdr(data, size);
+ _ubus_parse_msg(data, size);
+
+ return 0;
+}