Skip to content

Commit 9152773

Browse files
[CDRIVER-5859] Enable sign-compare warnings globally, and fix them all (#1856)
* Add a statement macro that can assert SIGABRT The `mlib_assert_aborts` macro checks that the following statement terminates the process with SIGABRT. This relies on `fork()`, so it only works on Unix systems. On Win32 it is a no-op. * New test assertion macro * Integer range looping macro. `mlib_foreach_irange` and `mlib_foreach_urange` provide concise looping over an integral range. * Looping over arrays * Replace all sign-compare loops with macro loops. This change swaps any `for (...)` loops that trigger `-Wsign-compare` with `mlib/loop` macros. This also simplifies redundant code around looping over array elements. * Integer encoding utilities. This adds function for reading little-endian i32, u32, i64, and u64 from pointers to memory. This allows us to decode integers in a single line instead of doing a declare+memcpy+byteswap that clutters the code and prevents us from using `const` and correct signedness. Instead, we can declare and initialize integers of the exact size and sign that we want in a single line. * Use integer decoding functions throughout the codebase * Enable sign-compare warnings globally, and fix every occurrence
1 parent 01101f4 commit 9152773

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1096
-543
lines changed

.clang-format

+5
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,12 @@ ForEachMacros:
105105
- foreach
106106
- Q_FOREACH
107107
- BOOST_FOREACH
108+
- mlib_foreach_irange
109+
- mlib_foreach_urange
110+
- mlib_foreach
111+
- mlib_foreach_arr
108112
IfMacros:
113+
- mlib_assert_aborts
109114
- KJ_IF_MAYBE
110115
IncludeBlocks: Preserve
111116
IncludeCategories:

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ if(ENABLE_MAINTAINER_FLAGS)
322322
gnu-like:-Wuninitialized
323323
# Disabled, for now:
324324
gnu-like:-Wno-strict-aliasing
325+
# Sign-comparison-mismatch:
326+
gnu-like:-Wsign-compare
327+
msvc:/we4018
325328
)
326329
endif()
327330

src/common/src/common-b64.c

+30-35
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
#include <bson/bson.h>
4444
#include <common-b64-private.h>
45+
#include <mlib/loop.h>
4546

4647
#define Assert(Cond) \
4748
if (!(Cond)) \
@@ -118,21 +119,21 @@ mcommon_b64_ntop (uint8_t const *src, size_t srclength, char *target, size_t tar
118119
size_t datalength = 0;
119120
uint8_t input[3];
120121
uint8_t output[4];
121-
size_t i;
122122

123123
if (!target) {
124124
return -1;
125125
}
126126

127-
while (2 < srclength) {
127+
// While we have at least three chars to read:
128+
while (srclength > 2) {
128129
input[0] = *src++;
129130
input[1] = *src++;
130131
input[2] = *src++;
131132
srclength -= 3;
132133

133134
output[0] = input[0] >> 2;
134-
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
135-
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
135+
output[1] = (uint8_t) (((input[0] & 0x03) << 4) + (input[1] >> 4));
136+
output[2] = (uint8_t) (((input[1] & 0x0f) << 2) + (input[2] >> 6));
136137
output[3] = input[2] & 0x3f;
137138
Assert (output[0] < 64);
138139
Assert (output[1] < 64);
@@ -153,12 +154,10 @@ mcommon_b64_ntop (uint8_t const *src, size_t srclength, char *target, size_t tar
153154
/* Get what's left. */
154155
input[0] = input[1] = input[2] = '\0';
155156

156-
for (i = 0; i < srclength; i++) {
157-
input[i] = *src++;
158-
}
157+
memcpy (input, src, srclength);
159158
output[0] = input[0] >> 2;
160-
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
161-
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
159+
output[1] = (uint8_t) (((input[0] & 0x03) << 4) + (input[1] >> 4));
160+
output[2] = (uint8_t) (((input[1] & 0x0f) << 2) + (input[2] >> 6));
162161
Assert (output[0] < 64);
163162
Assert (output[1] < 64);
164163
Assert (output[2] < 64);
@@ -277,27 +276,24 @@ static const uint8_t mongoc_b64rmap_invalid = 0xff;
277276

278277
static MONGOC_COMMON_ONCE_FUN (bson_b64_initialize_rmap)
279278
{
280-
int i;
281-
unsigned char ch;
282-
283279
/* Null: end of string, stop parsing */
284280
mongoc_b64rmap[0] = mongoc_b64rmap_end;
285281

286-
for (i = 1; i < 256; ++i) {
287-
ch = (unsigned char) i;
282+
mlib_foreach_urange (i, 1, 256) {
283+
const uint8_t ch = (uint8_t) i;
288284
/* Whitespaces */
289285
if (bson_isspace (ch))
290-
mongoc_b64rmap[i] = mongoc_b64rmap_space;
286+
mongoc_b64rmap[ch] = mongoc_b64rmap_space;
291287
/* Padding: stop parsing */
292288
else if (ch == Pad64)
293-
mongoc_b64rmap[i] = mongoc_b64rmap_end;
289+
mongoc_b64rmap[ch] = mongoc_b64rmap_end;
294290
/* Non-base64 char */
295291
else
296-
mongoc_b64rmap[i] = mongoc_b64rmap_invalid;
292+
mongoc_b64rmap[ch] = mongoc_b64rmap_invalid;
297293
}
298294

299295
/* Fill reverse mapping for base64 chars */
300-
for (i = 0; Base64[i] != '\0'; ++i)
296+
for (uint8_t i = 0; Base64[i] != '\0'; ++i)
301297
mongoc_b64rmap[(uint8_t) Base64[i]] = i;
302298

303299
MONGOC_COMMON_ONCE_RETURN;
@@ -313,7 +309,7 @@ mongoc_b64_pton_do (char const *src, uint8_t *target, size_t targsize)
313309
tarindex = 0;
314310

315311
while (1) {
316-
ch = *src++;
312+
ch = (uint8_t) *src++;
317313
ofs = mongoc_b64rmap[ch];
318314

319315
if (ofs >= mongoc_b64rmap_special) {
@@ -367,22 +363,22 @@ mongoc_b64_pton_do (char const *src, uint8_t *target, size_t targsize)
367363
* on a byte boundary, and/or with erroneous trailing characters.
368364
*/
369365

370-
if (ch == Pad64) { /* We got a pad char. */
371-
ch = *src++; /* Skip it, get next. */
366+
if (ch == Pad64) { /* We got a pad char. */
367+
ch = (uint8_t) *src++; /* Skip it, get next. */
372368
switch (state) {
373369
case 0: /* Invalid = in first position */
374370
case 1: /* Invalid = in second position */
375371
return (-1);
376372

377373
case 2: /* Valid, means one byte of info */
378374
/* Skip any number of spaces. */
379-
for ((void) NULL; ch != '\0'; ch = *src++)
375+
for ((void) NULL; ch != '\0'; ch = (uint8_t) *src++)
380376
if (mongoc_b64rmap[ch] != mongoc_b64rmap_space)
381377
break;
382378
/* Make sure there is another trailing = sign. */
383379
if (ch != Pad64)
384380
return (-1);
385-
ch = *src++; /* Skip the = */
381+
ch = (uint8_t) *src++; /* Skip the = */
386382
/* Fall through to "single trailing =" case. */
387383
/* FALLTHROUGH */
388384

@@ -391,7 +387,7 @@ mongoc_b64_pton_do (char const *src, uint8_t *target, size_t targsize)
391387
* We know this char is an =. Is there anything but
392388
* whitespace after it?
393389
*/
394-
for ((void) NULL; ch != '\0'; ch = *src++)
390+
for ((void) NULL; ch != '\0'; ch = (uint8_t) *src++)
395391
if (mongoc_b64rmap[ch] != mongoc_b64rmap_space)
396392
return (-1);
397393

@@ -422,14 +418,13 @@ mongoc_b64_pton_do (char const *src, uint8_t *target, size_t targsize)
422418
static int
423419
mongoc_b64_pton_len (char const *src)
424420
{
425-
int tarindex, state;
426-
uint8_t ch, ofs;
427-
428-
state = 0;
429-
tarindex = 0;
421+
uint8_t ch = 0;
422+
uint8_t ofs = 0;
423+
int state = 0;
424+
int tarindex = 0;
430425

431426
while (1) {
432-
ch = *src++;
427+
ch = (uint8_t) *src++;
433428
ofs = mongoc_b64rmap[ch];
434429

435430
if (ofs >= mongoc_b64rmap_special) {
@@ -469,22 +464,22 @@ mongoc_b64_pton_len (char const *src)
469464
* on a byte boundary, and/or with erroneous trailing characters.
470465
*/
471466

472-
if (ch == Pad64) { /* We got a pad char. */
473-
ch = *src++; /* Skip it, get next. */
467+
if (ch == Pad64) { /* We got a pad char. */
468+
ch = (uint8_t) *src++; /* Skip it, get next. */
474469
switch (state) {
475470
case 0: /* Invalid = in first position */
476471
case 1: /* Invalid = in second position */
477472
return (-1);
478473

479474
case 2: /* Valid, means one byte of info */
480475
/* Skip any number of spaces. */
481-
for ((void) NULL; ch != '\0'; ch = *src++)
476+
for ((void) NULL; ch != '\0'; ch = (uint8_t) *src++)
482477
if (mongoc_b64rmap[ch] != mongoc_b64rmap_space)
483478
break;
484479
/* Make sure there is another trailing = sign. */
485480
if (ch != Pad64)
486481
return (-1);
487-
ch = *src++; /* Skip the = */
482+
ch = (uint8_t) *src++; /* Skip the = */
488483
/* Fall through to "single trailing =" case. */
489484
/* FALLTHROUGH */
490485

@@ -493,7 +488,7 @@ mongoc_b64_pton_len (char const *src)
493488
* We know this char is an =. Is there anything but
494489
* whitespace after it?
495490
*/
496-
for ((void) NULL; ch != '\0'; ch = *src++)
491+
for (; ch != '\0'; ch = (uint8_t) *src++)
497492
if (mongoc_b64rmap[ch] != mongoc_b64rmap_space)
498493
return (-1);
499494

src/common/src/common-md5.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ void
338338
mcommon_md5_append (bson_md5_t *pms, const uint8_t *data, uint32_t nbytes)
339339
{
340340
const uint8_t *p = data;
341-
int left = nbytes;
342-
int offset = (pms->count[0] >> 3) & 63;
341+
uint32_t left = nbytes;
342+
uint8_t offset = (pms->count[0] >> 3) & 63;
343343
uint32_t nbits = (uint32_t) (nbytes << 3);
344344

345345
if (nbytes <= 0)
@@ -353,7 +353,7 @@ mcommon_md5_append (bson_md5_t *pms, const uint8_t *data, uint32_t nbytes)
353353

354354
/* Process an initial partial block. */
355355
if (offset) {
356-
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
356+
uint32_t copy = (offset + nbytes > 64u ? 64u - offset : nbytes);
357357

358358
memcpy (pms->buf + offset, p, copy);
359359
if (offset + copy < 64)

src/common/src/common-string.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ mcommon_string_append_base64_encode (mcommon_string_append_t *append, const uint
200200
if (encoded_target_len <= (size_t) max_append_len) {
201201
// No truncation needed. Grow the buffer and encode directly.
202202
mcommon_string_grow_to_capacity (string, old_len + encoded_target_len);
203-
BSON_ASSERT (encoded_target_len ==
204-
mcommon_b64_ntop (bytes, (size_t) len, string->str + old_len, encoded_target_len + 1));
203+
const int tgt = mcommon_b64_ntop (bytes, (size_t) len, string->str + old_len, encoded_target_len + 1);
204+
BSON_ASSERT (mlib_cmp (encoded_target_len, ==, tgt));
205205
BSON_ASSERT (mlib_in_range (uint32_t, encoded_target_len));
206206
string->len = old_len + (uint32_t) encoded_target_len;
207207
return true;
@@ -227,18 +227,18 @@ mcommon_string_append_base64_encode (mcommon_string_append_t *append, const uint
227227
uint32_t direct_input_len = mcommon_b64_pton_calculate_target_size ((size_t) direct_encoded_len);
228228
BSON_ASSERT (direct_input_len % 3 == 0);
229229
BSON_ASSERT (direct_input_len < len);
230-
BSON_ASSERT (direct_encoded_len ==
231-
mcommon_b64_ntop (bytes, (size_t) direct_input_len, string->str + old_len, direct_encoded_len + 1));
230+
const int tgt =
231+
mcommon_b64_ntop (bytes, (size_t) direct_input_len, string->str + old_len, direct_encoded_len + 1);
232+
BSON_ASSERT (mlib_cmp (direct_encoded_len, ==, tgt));
232233

233234
char remainder_buffer[5];
234235
uint32_t remainder_input_len = BSON_MIN (3, len - direct_input_len);
235236
BSON_ASSERT (remainder_input_len > 0);
236237
uint32_t remainder_encoded_len = mcommon_b64_ntop_calculate_target_size ((size_t) remainder_input_len) - 1;
237238
BSON_ASSERT (remainder_encoded_len > remainder_truncated_len);
238-
BSON_ASSERT (remainder_encoded_len == mcommon_b64_ntop (bytes + direct_input_len,
239-
(size_t) remainder_input_len,
240-
remainder_buffer,
241-
sizeof remainder_buffer));
239+
const int t2 = mcommon_b64_ntop (
240+
bytes + direct_input_len, (size_t) remainder_input_len, remainder_buffer, sizeof remainder_buffer);
241+
BSON_ASSERT (mlib_cmp (remainder_encoded_len, ==, t2));
242242
memcpy (buffer + old_len + direct_encoded_len, remainder_buffer, remainder_encoded_len);
243243

244244
BSON_ASSERT (old_len + direct_encoded_len + remainder_truncated_len == max_len);

src/common/src/mlib/config.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
#elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
176176
#define mlib_is_little_endian() (__BYTE_ORDER == __LITTLE_ENDIAN)
177177
#elif defined(_WIN32)
178-
#define mlib_is_mlib_is_little_endian() 1
178+
#define mlib_is_little_endian() 1
179179
#else
180180
#error "Do not know how to detect endianness on this platform."
181181
#endif
@@ -238,6 +238,8 @@
238238
#define mlib_pragma(...) _Pragma (#__VA_ARGS__) mlib_static_assert (1, "")
239239
#endif
240240

241+
#define MLIB_FUNC MLIB_IF_GNU_LIKE (__func__) MLIB_IF_MSVC (__FUNCTION__)
242+
241243
#define mlib_diagnostic_push() \
242244
MLIB_IF_GNU_LIKE (mlib_pragma (GCC diagnostic push);) \
243245
MLIB_IF_MSVC (mlib_pragma (warning (push));) \

0 commit comments

Comments
 (0)