Coverage Report

Created: 2025-10-24 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mosquitto/lib/property_mosq.c
Line
Count
Source
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
19.3M
{
37
19.3M
  int rc;
38
19.3M
  uint32_t property_identifier;
39
19.3M
  uint8_t byte;
40
19.3M
  uint8_t byte_count;
41
19.3M
  uint16_t uint16;
42
19.3M
  uint32_t uint32;
43
19.3M
  uint32_t varint;
44
19.3M
  char *str1, *str2;
45
19.3M
  uint16_t slen1, slen2;
46
47
19.3M
  if(!property){
48
0
    return MOSQ_ERR_INVAL;
49
0
  }
50
51
19.3M
  rc = packet__read_varint(packet, &property_identifier, NULL);
52
19.3M
  if(rc){
53
930
    return rc;
54
930
  }
55
19.3M
  *len -= mosquitto_varint_bytes(property_identifier);
56
57
19.3M
  memset(property, 0, sizeof(mosquitto_property));
58
59
19.3M
  property->identifier = (int32_t)property_identifier;
60
61
19.3M
  switch(property_identifier){
62
4.59M
    case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
63
8.93M
    case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:
64
9.60M
    case MQTT_PROP_REQUEST_RESPONSE_INFORMATION:
65
10.4M
    case MQTT_PROP_MAXIMUM_QOS:
66
11.9M
    case MQTT_PROP_RETAIN_AVAILABLE:
67
13.1M
    case MQTT_PROP_WILDCARD_SUB_AVAILABLE:
68
14.0M
    case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE:
69
14.8M
    case MQTT_PROP_SHARED_SUB_AVAILABLE:
70
14.8M
      rc = packet__read_byte(packet, &byte);
71
14.8M
      if(rc){
72
580
        return rc;
73
580
      }
74
14.8M
      *len -= 1; /* byte */
75
14.8M
      property->value.i8 = byte;
76
14.8M
      property->property_type = MQTT_PROP_TYPE_BYTE;
77
14.8M
      break;
78
79
419k
    case MQTT_PROP_SERVER_KEEP_ALIVE:
80
602k
    case MQTT_PROP_RECEIVE_MAXIMUM:
81
870k
    case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
82
965k
    case MQTT_PROP_TOPIC_ALIAS:
83
965k
      rc = packet__read_uint16(packet, &uint16);
84
965k
      if(rc){
85
315
        return rc;
86
315
      }
87
965k
      *len -= 2; /* uint16 */
88
965k
      property->value.i16 = uint16;
89
965k
      property->property_type = MQTT_PROP_TYPE_INT16;
90
965k
      break;
91
92
222k
    case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL:
93
336k
    case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
94
342k
    case MQTT_PROP_WILL_DELAY_INTERVAL:
95
503k
    case MQTT_PROP_MAXIMUM_PACKET_SIZE:
96
503k
      rc = packet__read_uint32(packet, &uint32);
97
503k
      if(rc){
98
309
        return rc;
99
309
      }
100
503k
      *len -= 4; /* uint32 */
101
503k
      property->value.i32 = uint32;
102
503k
      property->property_type = MQTT_PROP_TYPE_INT32;
103
503k
      break;
104
105
1.25M
    case MQTT_PROP_SUBSCRIPTION_IDENTIFIER:
106
1.25M
      rc = packet__read_varint(packet, &varint, &byte_count);
107
1.25M
      if(rc){
108
43
        return rc;
109
43
      }
110
1.25M
      *len -= byte_count;
111
1.25M
      property->value.varint = varint;
112
1.25M
      property->property_type = MQTT_PROP_TYPE_VARINT;
113
1.25M
      break;
114
115
163k
    case MQTT_PROP_CONTENT_TYPE:
116
314k
    case MQTT_PROP_RESPONSE_TOPIC:
117
483k
    case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER:
118
489k
    case MQTT_PROP_AUTHENTICATION_METHOD:
119
497k
    case MQTT_PROP_RESPONSE_INFORMATION:
120
511k
    case MQTT_PROP_SERVER_REFERENCE:
121
562k
    case MQTT_PROP_REASON_STRING:
122
562k
      rc = packet__read_string(packet, &str1, &slen1);
123
562k
      if(rc){
124
964
        return rc;
125
964
      }
126
561k
      *len = (*len) - 2 - slen1; /* uint16, string len */
127
561k
      property->value.s.v = str1;
128
561k
      property->value.s.len = slen1;
129
561k
      property->property_type = MQTT_PROP_TYPE_STRING;
130
561k
      break;
131
132
747k
    case MQTT_PROP_AUTHENTICATION_DATA:
133
1.14M
    case MQTT_PROP_CORRELATION_DATA:
134
1.14M
      rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1);
135
1.14M
      if(rc){
136
397
        return rc;
137
397
      }
138
1.14M
      *len = (*len) - 2 - slen1; /* uint16, binary len */
139
1.14M
      property->value.bin.v = str1;
140
1.14M
      property->value.bin.len = slen1;
141
1.14M
      property->property_type = MQTT_PROP_TYPE_BINARY;
142
1.14M
      break;
143
144
11.6k
    case MQTT_PROP_USER_PROPERTY:
145
11.6k
      rc = packet__read_string(packet, &str1, &slen1);
146
11.6k
      if(rc){
147
88
        return rc;
148
88
      }
149
11.5k
      *len = (*len) - 2 - slen1; /* uint16, string len */
150
151
11.5k
      rc = packet__read_string(packet, &str2, &slen2);
152
11.5k
      if(rc){
153
106
        mosquitto_FREE(str1);
154
106
        return rc;
155
106
      }
156
11.4k
      *len = (*len) - 2 - slen2; /* uint16, string len */
157
158
11.4k
      property->name.v = str1;
159
11.4k
      property->name.len = slen1;
160
11.4k
      property->value.s.v = str2;
161
11.4k
      property->value.s.len = slen2;
162
11.4k
      property->property_type = MQTT_PROP_TYPE_STRING_PAIR;
163
11.4k
      break;
164
165
1.01k
    default:
166
1.01k
#ifdef WITH_BROKER
167
1.01k
      log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier);
168
1.01k
#endif
169
1.01k
      return MOSQ_ERR_MALFORMED_PACKET;
170
19.3M
  }
171
172
19.3M
  return MOSQ_ERR_SUCCESS;
173
19.3M
}
174
175
176
int property__read_all(int command, struct mosquitto__packet_in *packet, mosquitto_property **properties)
177
14.3k
{
178
14.3k
  int rc;
179
14.3k
  uint32_t proplen;
180
14.3k
  mosquitto_property *p, *tail = NULL;
181
182
14.3k
  rc = packet__read_varint(packet, &proplen, NULL);
183
14.3k
  if(rc){
184
131
    return rc;
185
131
  }
186
187
14.1k
  *properties = NULL;
188
189
  /* The order of properties must be preserved for some types, so keep the
190
   * same order for all */
191
19.3M
  while(proplen > 0){
192
19.3M
    p = mosquitto_calloc(1, sizeof(mosquitto_property));
193
19.3M
    if(!p){
194
0
      mosquitto_property_free_all(properties);
195
0
      return MOSQ_ERR_NOMEM;
196
0
    }
197
198
19.3M
    rc = property__read(packet, &proplen, p);
199
19.3M
    if(rc){
200
4.74k
      mosquitto_FREE(p);
201
4.74k
      mosquitto_property_free_all(properties);
202
4.74k
      return rc;
203
4.74k
    }
204
205
19.3M
    if(!(*properties)){
206
10.8k
      *properties = p;
207
19.3M
    }else{
208
19.3M
      tail->next = p;
209
19.3M
    }
210
19.3M
    tail = p;
211
212
19.3M
  }
213
214
9.44k
  rc = mosquitto_property_check_all(command, *properties);
215
9.44k
  if(rc){
216
956
    mosquitto_property_free_all(properties);
217
956
    return rc;
218
956
  }
219
8.49k
  return MOSQ_ERR_SUCCESS;
220
9.44k
}
221
222
223
static int property__write(struct mosquitto__packet *packet, const mosquitto_property *property)
224
1.30k
{
225
1.30k
  int rc;
226
227
1.30k
  rc = packet__write_varint(packet, (uint32_t)mosquitto_property_identifier(property));
228
1.30k
  if(rc){
229
0
    return rc;
230
0
  }
231
232
1.30k
  switch(property->property_type){
233
1.30k
    case MQTT_PROP_TYPE_BYTE:
234
1.30k
      packet__write_byte(packet, property->value.i8);
235
1.30k
      break;
236
237
0
    case MQTT_PROP_TYPE_INT16:
238
0
      packet__write_uint16(packet, property->value.i16);
239
0
      break;
240
241
0
    case MQTT_PROP_TYPE_INT32:
242
0
      packet__write_uint32(packet, property->value.i32);
243
0
      break;
244
245
0
    case MQTT_PROP_TYPE_VARINT:
246
0
      return packet__write_varint(packet, property->value.varint);
247
248
0
    case MQTT_PROP_TYPE_STRING:
249
0
      packet__write_string(packet, property->value.s.v, property->value.s.len);
250
0
      break;
251
252
0
    case MQTT_PROP_TYPE_BINARY:
253
0
      packet__write_uint16(packet, property->value.bin.len);
254
0
      packet__write_bytes(packet, property->value.bin.v, property->value.bin.len);
255
0
      break;
256
257
0
    case MQTT_PROP_TYPE_STRING_PAIR:
258
0
      packet__write_string(packet, property->name.v, property->name.len);
259
0
      packet__write_string(packet, property->value.s.v, property->value.s.len);
260
0
      break;
261
262
0
    default:
263
0
#ifdef WITH_BROKER
264
0
      log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier);
265
0
#endif
266
0
      return MOSQ_ERR_INVAL;
267
1.30k
  }
268
269
1.30k
  return MOSQ_ERR_SUCCESS;
270
1.30k
}
271
272
273
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len)
274
1.49k
{
275
1.49k
  int rc;
276
1.49k
  const mosquitto_property *p;
277
278
1.49k
  if(write_len){
279
1.49k
    rc = packet__write_varint(packet, mosquitto_property_get_length_all(properties));
280
1.49k
    if(rc){
281
0
      return rc;
282
0
    }
283
1.49k
  }
284
285
1.49k
  p = properties;
286
2.80k
  while(p){
287
1.30k
    rc = property__write(packet, p);
288
1.30k
    if(rc){
289
0
      return rc;
290
0
    }
291
1.30k
    p = p->next;
292
1.30k
  }
293
294
1.49k
  return MOSQ_ERR_SUCCESS;
295
1.49k
}