Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fuzzing/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ all:
zip -r corpora/db_dump_seed_corpus.zip ../test/apps/db_dump/data/
$(MAKE) -C apps $@
$(MAKE) -C broker $@
$(MAKE) -C client $@
$(MAKE) -C libcommon $@
$(MAKE) -C plugins $@

Expand All @@ -14,5 +15,6 @@ clean:
-rm -f corpora/db_dump_seed_corpus.zip
$(MAKE) -C apps $@
$(MAKE) -C broker $@
$(MAKE) -C client $@
$(MAKE) -C libcommon $@
$(MAKE) -C plugins $@
34 changes: 34 additions & 0 deletions fuzzing/client/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
R=../..
include ${R}/fuzzing/config.mk

.PHONY: all clean

PACKET_FUZZERS:= \
client_fuzz_read_handle

# IMPORTANT: these -D flags must exactly match the ones used to compile
# lib/libmosquitto.a (see config.mk with WITH_FUZZING=yes). A mismatch changes
# the layout of `struct mosquitto` between this harness and the library and
# leads to memory corruption. In particular WITH_WEBSOCKETS=WS_IS_BUILTIN adds
# fields to the struct, and WITH_BROKER must NOT be defined for the client lib.
LOCAL_CPPFLAGS+=-I${R}/include/ -I${R}/lib -I${R} -I${R}/common \
-I${R}/deps -I${R}/deps/picohttpparser \
-DWITH_THREADING -DWITH_TLS -DWITH_TLS_PSK -DWITH_SOCKS \
-DWITH_UNIX_SOCKETS -DWITH_WEBSOCKETS=WS_IS_BUILTIN -DWITH_FUZZING
LOCAL_CXXFLAGS+=-g -Wall -Werror -pthread
LOCAL_CFLAGS+=-g -Wall -Werror -pthread
LOCAL_LDFLAGS+=
LOCAL_LIBADD+=$(LIB_FUZZING_ENGINE) -lssl -lcrypto -lcjson -lm \
${R}/libcommon/libmosquitto_common.a \
-Wl,-Bdynamic -Wl,-Bstatic -largon2 -Wl,-Bdynamic
LIBMOSQ_A=${R}/lib/libmosquitto.a

all: $(PACKET_FUZZERS)

${PACKET_FUZZERS} : %: %.c ${R}/lib/libmosquitto.a
$(CC) $(LOCAL_CFLAGS) $(LOCAL_CPPFLAGS) $(LOCAL_LDFLAGS) -o $@ $< $(LIBMOSQ_A) $(LOCAL_LIBADD)
install $@ ${OUT}/$@
cp ${R}/fuzzing/corpora/client_packet_seed_corpus.zip ${OUT}/$@_seed_corpus.zip

clean:
rm -f *.o $(PACKET_FUZZERS)
80 changes: 80 additions & 0 deletions fuzzing/client/client_fuzz_read_handle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright (c) 2026 Cedalo GmbH

All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
and Eclipse Distribution License v1.0 which accompany this distribution.

The Eclipse Public License is available at
https://www.eclipse.org/legal/epl-2.0/
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.

SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause

Contributors:
AdaLogics - client-side read-handle fuzzer.
*/

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "mosquitto.h"
#include "mosquitto/libcommon_memory.h"
#include "mosquitto_internal.h"
#include "packet_mosq.h"
#include "read_handle.h"

#define kMinInputLength 3
#define kMaxInputLength 268435455U

static int initialised = 0;

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct mosquitto *mosq;
uint8_t *payload;
size_t payload_len;

if(size < kMinInputLength || size > kMaxInputLength){
return 0;
}

if(!initialised){
mosquitto_lib_init();
initialised = 1;
}

mosq = mosquitto_new("fuzz-client", true, NULL);
if(!mosq){
return 0;
}

/* Put the client in a connected state; v5 also exercises the property parser */
mosq->protocol = (data[0] & 0x01) ? mosq_p_mqtt311 : mosq_p_mqtt5;
mosq->state = mosq_cs_connected;
mosq->alias_max_l2r = 10;

payload_len = size - 1;
payload = (uint8_t *)mosquitto_malloc(payload_len);
if(!payload){
mosquitto_destroy(mosq);
return 0;
}
memcpy(payload, &data[1], payload_len);

/* Stage the bytes as a received packet with the command byte consumed (pos=1) */
mosq->in_packet.command = payload[0];
mosq->in_packet.payload = payload;
mosq->in_packet.packet_length = (uint32_t)payload_len;
mosq->in_packet.remaining_length = (uint32_t)(payload_len - 1);
mosq->in_packet.pos = 1;

handle__packet(mosq);

packet__cleanup(&mosq->in_packet);
mosquitto_destroy(mosq);

return 0;
}