Coverage Report

Created: 2026-10-17 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/librabbitmq/fuzz/fuzz_read_message.c
Line
Count
Source
1
// Copyright 2007 - 2026, 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_socket.h"
12
13
11.3k
#define MAX_INPUT_SIZE (1U << 20)
14
239k
#define MAX_BODY_SIZE (1U << 20)
15
16
struct fuzz_socket_t {
17
  const struct amqp_socket_class_t *klass;
18
  const uint8_t *data;
19
  size_t size;
20
  size_t offset;
21
};
22
23
static ssize_t fuzz_socket_send(AMQP_UNUSED void *base,
24
                                AMQP_UNUSED const void *buf, size_t len,
25
0
                                AMQP_UNUSED int flags) {
26
0
  return (ssize_t)len;
27
0
}
28
29
static ssize_t fuzz_socket_recv(void *base, void *buf, size_t len,
30
7.74k
                                AMQP_UNUSED int flags) {
31
7.74k
  struct fuzz_socket_t *socket = (struct fuzz_socket_t *)base;
32
7.74k
  size_t remaining = socket->size - socket->offset;
33
7.74k
  size_t count;
34
35
7.74k
  if (remaining == 0) {
36
2.07k
    return AMQP_STATUS_CONNECTION_CLOSED;
37
2.07k
  }
38
39
5.66k
  count = remaining < len ? remaining : len;
40
5.66k
  memcpy(buf, socket->data + socket->offset, count);
41
5.66k
  socket->offset += count;
42
5.66k
  return (ssize_t)count;
43
7.74k
}
44
45
static int fuzz_socket_open(AMQP_UNUSED void *base,
46
                            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
0
                             AMQP_UNUSED amqp_socket_close_enum force) {
54
0
  return AMQP_STATUS_OK;
55
0
}
56
57
2.07k
static int fuzz_socket_get_sockfd(AMQP_UNUSED void *base) { return 0; }
58
59
5.57k
static void fuzz_socket_delete(void *base) { free(base); }
60
61
static const struct amqp_socket_class_t fuzz_socket_class = {
62
    fuzz_socket_send, fuzz_socket_recv,       fuzz_socket_open,
63
    fuzz_socket_close, fuzz_socket_get_sockfd, fuzz_socket_delete};
64
65
239k
static uint64_t read_be64(const uint8_t *data) {
66
239k
  uint64_t value = 0;
67
239k
  size_t i;
68
69
2.15M
  for (i = 0; i < 8; i++) {
70
1.91M
    value = (value << 8) | data[i];
71
1.91M
  }
72
239k
  return value;
73
239k
}
74
75
5.65k
static int body_sizes_are_bounded(const uint8_t *data, size_t size) {
76
5.65k
  size_t offset = 0;
77
78
5.65k
  if (size >= 8 && memcmp(data, "AMQP", 4) == 0) {
79
102
    offset = 8;
80
102
  }
81
82
390k
  while (size - offset >= 8) {
83
385k
    uint32_t payload_size = ((uint32_t)data[offset + 3] << 24) |
84
385k
                            ((uint32_t)data[offset + 4] << 16) |
85
385k
                            ((uint32_t)data[offset + 5] << 8) |
86
385k
                            (uint32_t)data[offset + 6];
87
385k
    size_t frame_size = (size_t)payload_size + 8;
88
89
385k
    if (frame_size > size - offset) {
90
439
      break;
91
439
    }
92
385k
    if (data[offset] == AMQP_FRAME_HEADER && payload_size >= 12 &&
93
239k
        read_be64(data + offset + 11) > MAX_BODY_SIZE) {
94
78
      return 0;
95
78
    }
96
385k
    offset += frame_size;
97
385k
  }
98
99
5.57k
  return 1;
100
5.65k
}
101
102
5.65k
extern int LLVMFuzzerTestOneInput(const char *data, size_t size) {
103
5.65k
  amqp_connection_state_t connection;
104
5.65k
  amqp_message_t message;
105
5.65k
  struct fuzz_socket_t *socket;
106
5.65k
  amqp_rpc_reply_t reply;
107
108
5.65k
  if (size == 0 || size > MAX_INPUT_SIZE ||
109
5.65k
      !body_sizes_are_bounded((const uint8_t *)data, size)) {
110
78
    return 0;
111
78
  }
112
113
5.57k
  connection = amqp_new_connection();
114
5.57k
  if (connection == NULL) {
115
0
    return 0;
116
0
  }
117
118
5.57k
  socket = (struct fuzz_socket_t *)calloc(1, sizeof(*socket));
119
5.57k
  if (socket == NULL) {
120
0
    amqp_destroy_connection(connection);
121
0
    return 0;
122
0
  }
123
124
5.57k
  socket->klass = &fuzz_socket_class;
125
5.57k
  socket->data = (const uint8_t *)data;
126
5.57k
  socket->size = size;
127
5.57k
  amqp_set_socket(connection, (amqp_socket_t *)socket);
128
129
5.57k
  reply = amqp_read_message(connection, 1, &message, 0);
130
5.57k
  if (reply.reply_type == AMQP_RESPONSE_NORMAL) {
131
22
    amqp_destroy_message(&message);
132
22
  }
133
134
5.57k
  amqp_destroy_connection(connection);
135
5.57k
  return 0;
136
5.57k
}