Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/librabbitmq/fuzz/fuzz_server.c
Line
Count
Source
1
// Copyright 2007 - 2022, Alan Antonuk and the rabbitmq-c contributors.
2
// SPDX-License-Identifier: mit
3
4
#include <stdint.h>
5
#include <stdlib.h>
6
#include <string.h>
7
8
#include <rabbitmq-c/amqp.h>
9
#include <rabbitmq-c/framing.h>
10
11
#include "amqp_private.h"
12
#include "amqp_socket.h"
13
14
// In-memory socket: feeds the fuzz buffer to the client as the bytes a broker
15
// would send, with no real socket or thread, so amqp_login() drives the full
16
// client handshake (Connection.Start -> Tune -> Open -> OpenOk) from the input.
17
18
struct fuzz_socket_t {
19
  const struct amqp_socket_class_t *klass;
20
  const uint8_t *data;
21
  size_t size;
22
  size_t offset;
23
};
24
25
static ssize_t fuzz_socket_send(AMQP_UNUSED void *base,
26
                                AMQP_UNUSED const void *buf, size_t len,
27
44
                                AMQP_UNUSED int flags) {
28
44
  return (ssize_t)len;
29
44
}
30
31
static ssize_t fuzz_socket_recv(void *base, void *buf, size_t len,
32
49
                                AMQP_UNUSED int flags) {
33
49
  struct fuzz_socket_t *self = (struct fuzz_socket_t *)base;
34
49
  size_t remaining = self->size - self->offset;
35
49
  size_t n;
36
37
49
  if (remaining == 0) {
38
5
    return AMQP_STATUS_CONNECTION_CLOSED;
39
5
  }
40
44
  n = remaining < len ? remaining : len;
41
44
  memcpy(buf, self->data + self->offset, n);
42
44
  self->offset += n;
43
44
  return (ssize_t)n;
44
49
}
45
46
static int fuzz_socket_open(AMQP_UNUSED void *base, AMQP_UNUSED const char *host,
47
                            AMQP_UNUSED int port,
48
0
                            AMQP_UNUSED const struct timeval *timeout) {
49
0
  return AMQP_STATUS_OK;
50
0
}
51
52
static int fuzz_socket_close(AMQP_UNUSED void *base,
53
44
                             AMQP_UNUSED amqp_socket_close_enum force) {
54
44
  return AMQP_STATUS_OK;
55
44
}
56
57
5
static int fuzz_socket_get_sockfd(AMQP_UNUSED void *base) {
58
5
  return 0; /* must be >= 0; -1 is treated as a closed connection */
59
5
}
60
61
44
static void fuzz_socket_delete(void *base) { free(base); }
62
63
static const struct amqp_socket_class_t fuzz_socket_class = {
64
    fuzz_socket_send, fuzz_socket_recv,       fuzz_socket_open,
65
    fuzz_socket_close, fuzz_socket_get_sockfd, fuzz_socket_delete};
66
67
44
extern int LLVMFuzzerTestOneInput(const char *data, size_t size) {
68
44
  amqp_connection_state_t conn;
69
44
  struct fuzz_socket_t *sock;
70
71
44
  if (size == 0) {
72
0
    return 0;
73
0
  }
74
75
44
  conn = amqp_new_connection();
76
44
  if (conn == NULL) {
77
0
    return 0;
78
0
  }
79
80
44
  sock = (struct fuzz_socket_t *)calloc(1, sizeof(*sock));
81
44
  if (sock == NULL) {
82
0
    amqp_destroy_connection(conn);
83
0
    return 0;
84
0
  }
85
44
  sock->klass = &fuzz_socket_class;
86
44
  sock->data = (const uint8_t *)data;
87
44
  sock->size = size;
88
89
  // Takes ownership; amqp_destroy_connection frees it via fuzz_socket_delete.
90
44
  amqp_set_socket(conn, (amqp_socket_t *)sock);
91
92
44
  amqp_login(conn, "/", 0, AMQP_DEFAULT_FRAME_SIZE, 0, AMQP_SASL_METHOD_PLAIN,
93
44
             "guest", "guest");
94
95
44
  amqp_destroy_connection(conn);
96
44
  return 0;
97
44
}