Coverage Report

Created: 2026-05-16 06:58

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