Coverage Report

Created: 2025-08-29 06:24

/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
0
{
37
0
  int rc;
38
0
  uint32_t property_identifier;
39
0
  uint8_t byte;
40
0
  uint8_t byte_count;
41
0
  uint16_t uint16;
42
0
  uint32_t uint32;
43
0
  uint32_t varint;
44
0
  char *str1, *str2;
45
0
  uint16_t slen1, slen2;
46
47
0
  if(!property) return MOSQ_ERR_INVAL;
48
49
0
  rc = packet__read_varint(packet, &property_identifier, NULL);
50
0
  if(rc){
51
0
    return rc;
52
0
  }
53
0
  *len -= 1;
54
55
0
  memset(property, 0, sizeof(mosquitto_property));
56
57
0
  property->identifier = (int32_t)property_identifier;
58
59
0
  switch(property_identifier){
60
0
    case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
61
0
    case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:
62
0
    case MQTT_PROP_REQUEST_RESPONSE_INFORMATION:
63
0
    case MQTT_PROP_MAXIMUM_QOS:
64
0
    case MQTT_PROP_RETAIN_AVAILABLE:
65
0
    case MQTT_PROP_WILDCARD_SUB_AVAILABLE:
66
0
    case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE:
67
0
    case MQTT_PROP_SHARED_SUB_AVAILABLE:
68
0
      rc = packet__read_byte(packet, &byte);
69
0
      if(rc) return rc;
70
0
      *len -= 1; /* byte */
71
0
      property->value.i8 = byte;
72
0
      property->property_type = MQTT_PROP_TYPE_BYTE;
73
0
      break;
74
75
0
    case MQTT_PROP_SERVER_KEEP_ALIVE:
76
0
    case MQTT_PROP_RECEIVE_MAXIMUM:
77
0
    case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
78
0
    case MQTT_PROP_TOPIC_ALIAS:
79
0
      rc = packet__read_uint16(packet, &uint16);
80
0
      if(rc) return rc;
81
0
      *len -= 2; /* uint16 */
82
0
      property->value.i16 = uint16;
83
0
      property->property_type = MQTT_PROP_TYPE_INT16;
84
0
      break;
85
86
0
    case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL:
87
0
    case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
88
0
    case MQTT_PROP_WILL_DELAY_INTERVAL:
89
0
    case MQTT_PROP_MAXIMUM_PACKET_SIZE:
90
0
      rc = packet__read_uint32(packet, &uint32);
91
0
      if(rc) return rc;
92
0
      *len -= 4; /* uint32 */
93
0
      property->value.i32 = uint32;
94
0
      property->property_type = MQTT_PROP_TYPE_INT32;
95
0
      break;
96
97
0
    case MQTT_PROP_SUBSCRIPTION_IDENTIFIER:
98
0
      rc = packet__read_varint(packet, &varint, &byte_count);
99
0
      if(rc) return rc;
100
0
      *len -= byte_count;
101
0
      property->value.varint = varint;
102
0
      property->property_type = MQTT_PROP_TYPE_VARINT;
103
0
      break;
104
105
0
    case MQTT_PROP_CONTENT_TYPE:
106
0
    case MQTT_PROP_RESPONSE_TOPIC:
107
0
    case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER:
108
0
    case MQTT_PROP_AUTHENTICATION_METHOD:
109
0
    case MQTT_PROP_RESPONSE_INFORMATION:
110
0
    case MQTT_PROP_SERVER_REFERENCE:
111
0
    case MQTT_PROP_REASON_STRING:
112
0
      rc = packet__read_string(packet, &str1, &slen1);
113
0
      if(rc) return rc;
114
0
      *len = (*len) - 2 - slen1; /* uint16, string len */
115
0
      property->value.s.v = str1;
116
0
      property->value.s.len = slen1;
117
0
      property->property_type = MQTT_PROP_TYPE_STRING;
118
0
      break;
119
120
0
    case MQTT_PROP_AUTHENTICATION_DATA:
121
0
    case MQTT_PROP_CORRELATION_DATA:
122
0
      rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1);
123
0
      if(rc) return rc;
124
0
      *len = (*len) - 2 - slen1; /* uint16, binary len */
125
0
      property->value.bin.v = str1;
126
0
      property->value.bin.len = slen1;
127
0
      property->property_type = MQTT_PROP_TYPE_BINARY;
128
0
      break;
129
130
0
    case MQTT_PROP_USER_PROPERTY:
131
0
      rc = packet__read_string(packet, &str1, &slen1);
132
0
      if(rc) return rc;
133
0
      *len = (*len) - 2 - slen1; /* uint16, string len */
134
135
0
      rc = packet__read_string(packet, &str2, &slen2);
136
0
      if(rc){
137
0
        mosquitto_FREE(str1);
138
0
        return rc;
139
0
      }
140
0
      *len = (*len) - 2 - slen2; /* uint16, string len */
141
142
0
      property->name.v = str1;
143
0
      property->name.len = slen1;
144
0
      property->value.s.v = str2;
145
0
      property->value.s.len = slen2;
146
0
      property->property_type = MQTT_PROP_TYPE_STRING_PAIR;
147
0
      break;
148
149
0
    default:
150
0
#ifdef WITH_BROKER
151
0
      log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier);
152
0
#endif
153
0
      return MOSQ_ERR_MALFORMED_PACKET;
154
0
  }
155
156
0
  return MOSQ_ERR_SUCCESS;
157
0
}
158
159
160
int property__read_all(int command, struct mosquitto__packet_in *packet, mosquitto_property **properties)
161
0
{
162
0
  int rc;
163
0
  uint32_t proplen;
164
0
  mosquitto_property *p, *tail = NULL;
165
166
0
  rc = packet__read_varint(packet, &proplen, NULL);
167
0
  if(rc) return rc;
168
169
0
  *properties = NULL;
170
171
  /* The order of properties must be preserved for some types, so keep the
172
   * same order for all */
173
0
  while(proplen > 0){
174
0
    p = mosquitto_calloc(1, sizeof(mosquitto_property));
175
0
    if(!p){
176
0
      mosquitto_property_free_all(properties);
177
0
      return MOSQ_ERR_NOMEM;
178
0
    }
179
180
0
    rc = property__read(packet, &proplen, p);
181
0
    if(rc){
182
0
      mosquitto_FREE(p);
183
0
      mosquitto_property_free_all(properties);
184
0
      return rc;
185
0
    }
186
187
0
    if(!(*properties)){
188
0
      *properties = p;
189
0
    }else{
190
0
      tail->next = p;
191
0
    }
192
0
    tail = p;
193
194
0
  }
195
196
0
  rc = mosquitto_property_check_all(command, *properties);
197
0
  if(rc){
198
0
    mosquitto_property_free_all(properties);
199
0
    return rc;
200
0
  }
201
0
  return MOSQ_ERR_SUCCESS;
202
0
}
203
204
205
static int property__write(struct mosquitto__packet *packet, const mosquitto_property *property)
206
0
{
207
0
  int rc;
208
209
0
  rc = packet__write_varint(packet, (uint32_t)mosquitto_property_identifier(property));
210
0
  if(rc) return rc;
211
212
0
  switch(property->property_type){
213
0
    case MQTT_PROP_TYPE_BYTE:
214
0
      packet__write_byte(packet, property->value.i8);
215
0
      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
0
  }
248
249
0
  return MOSQ_ERR_SUCCESS;
250
0
}
251
252
253
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len)
254
0
{
255
0
  int rc;
256
0
  const mosquitto_property *p;
257
258
0
  if(write_len){
259
0
    rc = packet__write_varint(packet, mosquitto_property_get_length_all(properties));
260
0
    if(rc) return rc;
261
0
  }
262
263
0
  p = properties;
264
0
  while(p){
265
0
    rc = property__write(packet, p);
266
0
    if(rc) return rc;
267
0
    p = p->next;
268
0
  }
269
270
0
  return MOSQ_ERR_SUCCESS;
271
0
}