Coverage Report

Created: 2025-08-26 06:48

/src/mosquitto/lib/property_mosq.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2018-2021 Roger Light <roger@atchoo.org>
3
4
All rights reserved. This program and the accompanying materials
5
are made available under the terms of the Eclipse Public License 2.0
6
and Eclipse Distribution License v1.0 which accompany this distribution.
7
8
The Eclipse Public License is available at
9
   https://www.eclipse.org/legal/epl-2.0/
10
and the Eclipse Distribution License is available at
11
  http://www.eclipse.org/org/documents/edl-v10.php.
12
13
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
14
15
Contributors:
16
   Roger Light - initial implementation and documentation.
17
*/
18
19
#include "config.h"
20
21
#include <errno.h>
22
#include <string.h>
23
24
#ifndef WIN32
25
#  include <strings.h>
26
#endif
27
28
#include "logging_mosq.h"
29
#include "mosquitto/mqtt_protocol.h"
30
#include "packet_mosq.h"
31
#include "property_common.h"
32
#include "property_mosq.h"
33
34
35
static int property__read(struct mosquitto__packet_in *packet, uint32_t *len, mosquitto_property *property)
36
24.5M
{
37
24.5M
  int rc;
38
24.5M
  uint32_t property_identifier;
39
24.5M
  uint8_t byte;
40
24.5M
  uint8_t byte_count;
41
24.5M
  uint16_t uint16;
42
24.5M
  uint32_t uint32;
43
24.5M
  uint32_t varint;
44
24.5M
  char *str1, *str2;
45
24.5M
  uint16_t slen1, slen2;
46
47
24.5M
  if(!property) return MOSQ_ERR_INVAL;
48
49
24.5M
  rc = packet__read_varint(packet, &property_identifier, NULL);
50
24.5M
  if(rc){
51
1.31k
    return rc;
52
1.31k
  }
53
24.5M
  *len -= 1;
54
55
24.5M
  memset(property, 0, sizeof(mosquitto_property));
56
57
24.5M
  property->identifier = (int32_t)property_identifier;
58
59
24.5M
  switch(property_identifier){
60
6.58M
    case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
61
10.4M
    case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:
62
11.1M
    case MQTT_PROP_REQUEST_RESPONSE_INFORMATION:
63
12.1M
    case MQTT_PROP_MAXIMUM_QOS:
64
13.6M
    case MQTT_PROP_RETAIN_AVAILABLE:
65
15.2M
    case MQTT_PROP_WILDCARD_SUB_AVAILABLE:
66
17.2M
    case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE:
67
18.3M
    case MQTT_PROP_SHARED_SUB_AVAILABLE:
68
18.3M
      rc = packet__read_byte(packet, &byte);
69
18.3M
      if(rc) return rc;
70
18.3M
      *len -= 1; /* byte */
71
18.3M
      property->value.i8 = byte;
72
18.3M
      property->property_type = MQTT_PROP_TYPE_BYTE;
73
18.3M
      break;
74
75
693k
    case MQTT_PROP_SERVER_KEEP_ALIVE:
76
1.03M
    case MQTT_PROP_RECEIVE_MAXIMUM:
77
1.64M
    case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
78
1.78M
    case MQTT_PROP_TOPIC_ALIAS:
79
1.78M
      rc = packet__read_uint16(packet, &uint16);
80
1.78M
      if(rc) return rc;
81
1.77M
      *len -= 2; /* uint16 */
82
1.77M
      property->value.i16 = uint16;
83
1.77M
      property->property_type = MQTT_PROP_TYPE_INT16;
84
1.77M
      break;
85
86
247k
    case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL:
87
404k
    case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
88
413k
    case MQTT_PROP_WILL_DELAY_INTERVAL:
89
645k
    case MQTT_PROP_MAXIMUM_PACKET_SIZE:
90
645k
      rc = packet__read_uint32(packet, &uint32);
91
645k
      if(rc) return rc;
92
645k
      *len -= 4; /* uint32 */
93
645k
      property->value.i32 = uint32;
94
645k
      property->property_type = MQTT_PROP_TYPE_INT32;
95
645k
      break;
96
97
1.21M
    case MQTT_PROP_SUBSCRIPTION_IDENTIFIER:
98
1.21M
      rc = packet__read_varint(packet, &varint, &byte_count);
99
1.21M
      if(rc) return rc;
100
1.21M
      *len -= byte_count;
101
1.21M
      property->value.varint = varint;
102
1.21M
      property->property_type = MQTT_PROP_TYPE_VARINT;
103
1.21M
      break;
104
105
279k
    case MQTT_PROP_CONTENT_TYPE:
106
366k
    case MQTT_PROP_RESPONSE_TOPIC:
107
518k
    case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER:
108
742k
    case MQTT_PROP_AUTHENTICATION_METHOD:
109
751k
    case MQTT_PROP_RESPONSE_INFORMATION:
110
808k
    case MQTT_PROP_SERVER_REFERENCE:
111
867k
    case MQTT_PROP_REASON_STRING:
112
867k
      rc = packet__read_string(packet, &str1, &slen1);
113
867k
      if(rc) return rc;
114
865k
      *len = (*len) - 2 - slen1; /* uint16, string len */
115
865k
      property->value.s.v = str1;
116
865k
      property->value.s.len = slen1;
117
865k
      property->property_type = MQTT_PROP_TYPE_STRING;
118
865k
      break;
119
120
1.20M
    case MQTT_PROP_AUTHENTICATION_DATA:
121
1.59M
    case MQTT_PROP_CORRELATION_DATA:
122
1.59M
      rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1);
123
1.59M
      if(rc) return rc;
124
1.59M
      *len = (*len) - 2 - slen1; /* uint16, binary len */
125
1.59M
      property->value.bin.v = str1;
126
1.59M
      property->value.bin.len = slen1;
127
1.59M
      property->property_type = MQTT_PROP_TYPE_BINARY;
128
1.59M
      break;
129
130
14.8k
    case MQTT_PROP_USER_PROPERTY:
131
14.8k
      rc = packet__read_string(packet, &str1, &slen1);
132
14.8k
      if(rc) return rc;
133
14.6k
      *len = (*len) - 2 - slen1; /* uint16, string len */
134
135
14.6k
      rc = packet__read_string(packet, &str2, &slen2);
136
14.6k
      if(rc){
137
133
        mosquitto_FREE(str1);
138
133
        return rc;
139
133
      }
140
14.5k
      *len = (*len) - 2 - slen2; /* uint16, string len */
141
142
14.5k
      property->name.v = str1;
143
14.5k
      property->name.len = slen1;
144
14.5k
      property->value.s.v = str2;
145
14.5k
      property->value.s.len = slen2;
146
14.5k
      property->property_type = MQTT_PROP_TYPE_STRING_PAIR;
147
14.5k
      break;
148
149
451
    default:
150
451
#ifdef WITH_BROKER
151
451
      log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier);
152
451
#endif
153
451
      return MOSQ_ERR_MALFORMED_PACKET;
154
24.5M
  }
155
156
24.5M
  return MOSQ_ERR_SUCCESS;
157
24.5M
}
158
159
160
int property__read_all(int command, struct mosquitto__packet_in *packet, mosquitto_property **properties)
161
15.8k
{
162
15.8k
  int rc;
163
15.8k
  uint32_t proplen;
164
15.8k
  mosquitto_property *p, *tail = NULL;
165
166
15.8k
  rc = packet__read_varint(packet, &proplen, NULL);
167
15.8k
  if(rc) return rc;
168
169
15.6k
  *properties = NULL;
170
171
  /* The order of properties must be preserved for some types, so keep the
172
   * same order for all */
173
24.5M
  while(proplen > 0){
174
24.5M
    p = mosquitto_calloc(1, sizeof(mosquitto_property));
175
24.5M
    if(!p){
176
0
      mosquitto_property_free_all(properties);
177
0
      return MOSQ_ERR_NOMEM;
178
0
    }
179
180
24.5M
    rc = property__read(packet, &proplen, p);
181
24.5M
    if(rc){
182
5.28k
      mosquitto_FREE(p);
183
5.28k
      mosquitto_property_free_all(properties);
184
5.28k
      return rc;
185
5.28k
    }
186
187
24.5M
    if(!(*properties)){
188
12.3k
      *properties = p;
189
24.4M
    }else{
190
24.4M
      tail->next = p;
191
24.4M
    }
192
24.5M
    tail = p;
193
194
24.5M
  }
195
196
10.3k
  rc = mosquitto_property_check_all(command, *properties);
197
10.3k
  if(rc){
198
1.30k
    mosquitto_property_free_all(properties);
199
1.30k
    return rc;
200
1.30k
  }
201
9.05k
  return MOSQ_ERR_SUCCESS;
202
10.3k
}
203
204
205
static int property__write(struct mosquitto__packet *packet, const mosquitto_property *property)
206
1.03k
{
207
1.03k
  int rc;
208
209
1.03k
  rc = packet__write_varint(packet, (uint32_t)mosquitto_property_identifier(property));
210
1.03k
  if(rc) return rc;
211
212
1.03k
  switch(property->property_type){
213
1.03k
    case MQTT_PROP_TYPE_BYTE:
214
1.03k
      packet__write_byte(packet, property->value.i8);
215
1.03k
      break;
216
217
0
    case MQTT_PROP_TYPE_INT16:
218
0
      packet__write_uint16(packet, property->value.i16);
219
0
      break;
220
221
0
    case MQTT_PROP_TYPE_INT32:
222
0
      packet__write_uint32(packet, property->value.i32);
223
0
      break;
224
225
0
    case MQTT_PROP_TYPE_VARINT:
226
0
      return packet__write_varint(packet, property->value.varint);
227
228
0
    case MQTT_PROP_TYPE_STRING:
229
0
      packet__write_string(packet, property->value.s.v, property->value.s.len);
230
0
      break;
231
232
0
    case MQTT_PROP_TYPE_BINARY:
233
0
      packet__write_uint16(packet, property->value.bin.len);
234
0
      packet__write_bytes(packet, property->value.bin.v, property->value.bin.len);
235
0
      break;
236
237
0
    case MQTT_PROP_TYPE_STRING_PAIR:
238
0
      packet__write_string(packet, property->name.v, property->name.len);
239
0
      packet__write_string(packet, property->value.s.v, property->value.s.len);
240
0
      break;
241
242
0
    default:
243
0
#ifdef WITH_BROKER
244
0
      log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier);
245
0
#endif
246
0
      return MOSQ_ERR_INVAL;
247
1.03k
  }
248
249
1.03k
  return MOSQ_ERR_SUCCESS;
250
1.03k
}
251
252
253
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len)
254
1.20k
{
255
1.20k
  int rc;
256
1.20k
  const mosquitto_property *p;
257
258
1.20k
  if(write_len){
259
1.20k
    rc = packet__write_varint(packet, mosquitto_property_get_length_all(properties));
260
1.20k
    if(rc) return rc;
261
1.20k
  }
262
263
1.20k
  p = properties;
264
2.24k
  while(p){
265
1.03k
    rc = property__write(packet, p);
266
1.03k
    if(rc) return rc;
267
1.03k
    p = p->next;
268
1.03k
  }
269
270
1.20k
  return MOSQ_ERR_SUCCESS;
271
1.20k
}