Coverage Report

Created: 2026-07-25 06:21

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
33.4M
{
37
33.4M
  int rc;
38
33.4M
  uint32_t property_identifier;
39
33.4M
  uint8_t byte;
40
33.4M
  uint8_t byte_count;
41
33.4M
  uint16_t uint16;
42
33.4M
  uint32_t uint32;
43
33.4M
  uint32_t varint;
44
33.4M
  char *str1, *str2;
45
33.4M
  uint16_t slen1, slen2;
46
47
33.4M
  if(!property){
48
0
    return MOSQ_ERR_INVAL;
49
0
  }
50
51
33.4M
  rc = packet__read_varint(packet, &property_identifier, NULL);
52
33.4M
  if(rc){
53
1.30k
    return rc;
54
1.30k
  }
55
33.4M
  *len -= mosquitto_varint_bytes(property_identifier);
56
57
33.4M
  memset(property, 0, sizeof(mosquitto_property));
58
59
33.4M
  property->identifier = (int32_t)property_identifier;
60
61
33.4M
  switch(property_identifier){
62
10.1M
    case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
63
16.8M
    case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:
64
18.3M
    case MQTT_PROP_REQUEST_RESPONSE_INFORMATION:
65
19.7M
    case MQTT_PROP_MAXIMUM_QOS:
66
21.6M
    case MQTT_PROP_RETAIN_AVAILABLE:
67
23.4M
    case MQTT_PROP_WILDCARD_SUB_AVAILABLE:
68
26.0M
    case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE:
69
27.4M
    case MQTT_PROP_SHARED_SUB_AVAILABLE:
70
27.4M
      rc = packet__read_byte(packet, &byte);
71
27.4M
      if(rc){
72
760
        return rc;
73
760
      }
74
27.4M
      *len -= 1; /* byte */
75
27.4M
      property->value.i8 = byte;
76
27.4M
      property->property_type = MQTT_PROP_TYPE_BYTE;
77
27.4M
      break;
78
79
400k
    case MQTT_PROP_SERVER_KEEP_ALIVE:
80
792k
    case MQTT_PROP_RECEIVE_MAXIMUM:
81
1.20M
    case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
82
1.29M
    case MQTT_PROP_TOPIC_ALIAS:
83
1.29M
      rc = packet__read_uint16(packet, &uint16);
84
1.29M
      if(rc){
85
388
        return rc;
86
388
      }
87
1.29M
      *len -= 2; /* uint16 */
88
1.29M
      property->value.i16 = uint16;
89
1.29M
      property->property_type = MQTT_PROP_TYPE_INT16;
90
1.29M
      break;
91
92
388k
    case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL:
93
454k
    case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
94
474k
    case MQTT_PROP_WILL_DELAY_INTERVAL:
95
571k
    case MQTT_PROP_MAXIMUM_PACKET_SIZE:
96
571k
      rc = packet__read_uint32(packet, &uint32);
97
571k
      if(rc){
98
401
        return rc;
99
401
      }
100
570k
      *len -= 4; /* uint32 */
101
570k
      property->value.i32 = uint32;
102
570k
      property->property_type = MQTT_PROP_TYPE_INT32;
103
570k
      break;
104
105
700k
    case MQTT_PROP_SUBSCRIPTION_IDENTIFIER:
106
700k
      rc = packet__read_varint(packet, &varint, &byte_count);
107
700k
      if(rc){
108
47
        return rc;
109
47
      }
110
700k
      *len -= byte_count;
111
700k
      property->value.varint = varint;
112
700k
      property->property_type = MQTT_PROP_TYPE_VARINT;
113
700k
      break;
114
115
169k
    case MQTT_PROP_CONTENT_TYPE:
116
422k
    case MQTT_PROP_RESPONSE_TOPIC:
117
622k
    case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER:
118
901k
    case MQTT_PROP_AUTHENTICATION_METHOD:
119
916k
    case MQTT_PROP_RESPONSE_INFORMATION:
120
939k
    case MQTT_PROP_SERVER_REFERENCE:
121
964k
    case MQTT_PROP_REASON_STRING:
122
964k
      rc = packet__read_string(packet, &str1, &slen1);
123
964k
      if(rc){
124
1.17k
        return rc;
125
1.17k
      }
126
963k
      *len = (*len) - 2 - slen1; /* uint16, string len */
127
963k
      property->value.s.v = str1;
128
963k
      property->value.s.len = slen1;
129
963k
      property->property_type = MQTT_PROP_TYPE_STRING;
130
963k
      break;
131
132
1.51M
    case MQTT_PROP_AUTHENTICATION_DATA:
133
2.43M
    case MQTT_PROP_CORRELATION_DATA:
134
2.43M
      rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1);
135
2.43M
      if(rc){
136
493
        return rc;
137
493
      }
138
2.43M
      *len = (*len) - 2 - slen1; /* uint16, binary len */
139
2.43M
      property->value.bin.v = str1;
140
2.43M
      property->value.bin.len = slen1;
141
2.43M
      property->property_type = MQTT_PROP_TYPE_BINARY;
142
2.43M
      break;
143
144
16.0k
    case MQTT_PROP_USER_PROPERTY:
145
16.0k
      rc = packet__read_string(packet, &str1, &slen1);
146
16.0k
      if(rc){
147
126
        return rc;
148
126
      }
149
15.9k
      *len = (*len) - 2 - slen1; /* uint16, string len */
150
151
15.9k
      rc = packet__read_string(packet, &str2, &slen2);
152
15.9k
      if(rc){
153
113
        mosquitto_FREE(str1);
154
113
        return rc;
155
113
      }
156
15.8k
      *len = (*len) - 2 - slen2; /* uint16, string len */
157
158
15.8k
      property->name.v = str1;
159
15.8k
      property->name.len = slen1;
160
15.8k
      property->value.s.v = str2;
161
15.8k
      property->value.s.len = slen2;
162
15.8k
      property->property_type = MQTT_PROP_TYPE_STRING_PAIR;
163
15.8k
      break;
164
165
1.31k
    default:
166
1.31k
#ifdef WITH_BROKER
167
1.31k
      log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier);
168
1.31k
#endif
169
1.31k
      return MOSQ_ERR_MALFORMED_PACKET;
170
33.4M
  }
171
172
33.4M
  return MOSQ_ERR_SUCCESS;
173
33.4M
}
174
175
176
int property__read_all(int command, struct mosquitto__packet_in *packet, mosquitto_property **properties)
177
19.6k
{
178
19.6k
  int rc;
179
19.6k
  uint32_t proplen;
180
19.6k
  mosquitto_property *p, *tail = NULL;
181
182
19.6k
  rc = packet__read_varint(packet, &proplen, NULL);
183
19.6k
  if(rc){
184
236
    return rc;
185
236
  }
186
187
19.4k
  *properties = NULL;
188
189
  /* The order of properties must be preserved for some types, so keep the
190
   * same order for all */
191
33.4M
  while(proplen > 0){
192
33.4M
    p = mosquitto_calloc(1, sizeof(mosquitto_property));
193
33.4M
    if(!p){
194
0
      mosquitto_property_free_all(properties);
195
0
      return MOSQ_ERR_NOMEM;
196
0
    }
197
198
33.4M
    rc = property__read(packet, &proplen, p);
199
33.4M
    if(rc){
200
6.11k
      mosquitto_FREE(p);
201
6.11k
      mosquitto_property_free_all(properties);
202
6.11k
      return rc;
203
6.11k
    }
204
205
33.4M
    if(!(*properties)){
206
14.8k
      *properties = p;
207
33.4M
    }else{
208
33.4M
      tail->next = p;
209
33.4M
    }
210
33.4M
    tail = p;
211
212
33.4M
  }
213
214
13.3k
  rc = mosquitto_property_check_all(command, *properties);
215
13.3k
  if(rc){
216
1.24k
    mosquitto_property_free_all(properties);
217
1.24k
    return rc;
218
1.24k
  }
219
12.0k
  return MOSQ_ERR_SUCCESS;
220
13.3k
}
221
222
223
static int property__write(struct mosquitto__packet *packet, const mosquitto_property *property)
224
1.14k
{
225
1.14k
  int rc;
226
227
1.14k
  rc = packet__write_varint(packet, (uint32_t)mosquitto_property_identifier(property));
228
1.14k
  if(rc){
229
0
    return rc;
230
0
  }
231
232
1.14k
  switch(property->property_type){
233
1.14k
    case MQTT_PROP_TYPE_BYTE:
234
1.14k
      packet__write_byte(packet, property->value.i8);
235
1.14k
      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.14k
  }
268
269
1.14k
  return MOSQ_ERR_SUCCESS;
270
1.14k
}
271
272
273
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len)
274
1.37k
{
275
1.37k
  int rc;
276
1.37k
  const mosquitto_property *p;
277
278
1.37k
  if(write_len){
279
1.37k
    rc = packet__write_varint(packet, mosquitto_property_get_length_all(properties));
280
1.37k
    if(rc){
281
0
      return rc;
282
0
    }
283
1.37k
  }
284
285
1.37k
  p = properties;
286
2.51k
  while(p){
287
1.14k
    rc = property__write(packet, p);
288
1.14k
    if(rc){
289
0
      return rc;
290
0
    }
291
1.14k
    p = p->next;
292
1.14k
  }
293
294
1.37k
  return MOSQ_ERR_SUCCESS;
295
1.37k
}