From: Timo Sirainen Date: Mon, 24 Feb 2025 11:28:10 +0000 (+0200) Subject: lib-settings, config: Use native CPU endianess in binary config file X-Git-Tag: 2.4.2~818 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41bd7a50210576f99b37c9122867da2788e594b1;p=thirdparty%2Fdovecot%2Fcore.git lib-settings, config: Use native CPU endianess in binary config file The binary config file is never shared between different servers, so for performance it's better to just use native endianess. --- diff --git a/src/config/config-dump-full.c b/src/config/config-dump-full.c index 23cf56b744..26d9a906f4 100644 --- a/src/config/config-dump-full.c +++ b/src/config/config-dump-full.c @@ -22,50 +22,51 @@ Config binary file format: The settings size numbers do not include the size integer itself. + All the numbers are in native CPU endianess. "DOVECOT-CONFIG\t1.0\n" - <64bit big-endian: settings full size> + <64bit: settings full size> - <32bit big-endian: number of paths used for caching> + <32bit: number of paths used for caching> Repeat for "number of paths": - <64bit big-endian: inode> - <64bit big-endian: size> - <32bit big-endian: mtime UNIX timestamp> - <32bit big-endian: mtime nsecs> - <32bit big-endian: ctime UNIX timestamp> - <32bit big-endian: ctime nsecs> - - <32bit big-endian: event filter strings count> + <64bit: inode> + <64bit: size> + <32bit: mtime UNIX timestamp> + <32bit: mtime nsecs> + <32bit: ctime UNIX timestamp> + <32bit: ctime nsecs> + + <32bit: event filter strings count> Repeat for "event filter strings count": Repeat until "settings full size" is reached: - <64bit big-endian: settings block size> + <64bit: settings block size> - <32bit big-endian: settings count> + <32bit: settings count> [settings count] - <32bit big-endian: filter count> + <32bit: filter count> Repeat for "filter count": - <64bit big-endian: filter settings size> + <64bit: filter settings size> - <32bit big-endian: include group count> + <32bit: include group count> Repeat for "include group count": Repeat until "filter settings size" is reached: - <32bit big-endian: key index number> + <32bit: key index number> [+|$ ] Repeat for "filter count": - <32bit big-endian: event filter string index number> + <32bit: event filter string index number> Repeat for "filter count": - <64bit big-endian: filter settings offset> + <64bit: filter settings offset> The order of filters is important in the output. lib-settings applies the @@ -115,8 +116,8 @@ struct dump_context { static int output_blob_size(struct ostream *output, uoff_t blob_size_offset) { i_assert(output->offset >= blob_size_offset + sizeof(uint64_t)); - uint64_t blob_size = cpu64_to_be(output->offset - - (blob_size_offset + sizeof(uint64_t))); + uint64_t blob_size = output->offset - + (blob_size_offset + sizeof(uint64_t)); if (o_stream_pwrite(output, &blob_size, sizeof(blob_size), blob_size_offset) < 0) { i_error("o_stream_pwrite(%s) failed: %s", @@ -151,21 +152,21 @@ config_dump_full_write_cache_paths(struct ostream *output, return; } - num32 = cpu32_to_be(array_count(config_parsed_get_paths(config))); + num32 = array_count(config_parsed_get_paths(config)); o_stream_nsend(output, &num32, sizeof(num32)); array_foreach(config_parsed_get_paths(config), path) { o_stream_nsend(output, path->path, strlen(path->path) + 1); - uint64_t num64 = cpu32_to_be(path->st.st_ino); + uint64_t num64 = path->st.st_ino; o_stream_nsend(output, &num64, sizeof(num64)); - num64 = cpu32_to_be(path->st.st_size); + num64 = path->st.st_size; o_stream_nsend(output, &num64, sizeof(num64)); - num32 = cpu32_to_be(path->st.st_mtime); + num32 = path->st.st_mtime; o_stream_nsend(output, &num32, sizeof(num32)); - num32 = cpu32_to_be(ST_MTIME_NSEC(path->st)); + num32 = ST_MTIME_NSEC(path->st); o_stream_nsend(output, &num32, sizeof(num32)); - num32 = cpu32_to_be(path->st.st_ctime); + num32 = path->st.st_ctime; o_stream_nsend(output, &num32, sizeof(num32)); - num32 = cpu32_to_be(ST_CTIME_NSEC(path->st)); + num32 = ST_CTIME_NSEC(path->st); o_stream_nsend(output, &num32, sizeof(num32)); } @@ -250,8 +251,8 @@ config_dump_full_write_filters(struct ostream *output, while (filters[filter_count] != NULL) filter_count++; - uint32_t filter_count_be32 = cpu32_to_be(filter_count); - o_stream_nsend(output, &filter_count_be32, sizeof(filter_count_be32)); + uint32_t filter_count_32 = filter_count; + o_stream_nsend(output, &filter_count_32, sizeof(filter_count_32)); /* the first filter is the global empty filter */ o_stream_nsend(output, "", 1); @@ -277,8 +278,8 @@ config_dump_full_write_keys(struct ostream *output, { unsigned int count = setting_parser_info_get_define_count(info); - uint32_t count_be32 = cpu32_to_be(count); - o_stream_nsend(output, &count_be32, sizeof(count_be32)); + uint32_t count_32 = count; + o_stream_nsend(output, &count_32, sizeof(count_32)); for (unsigned int i = 0; i < count; i++) { const char *key = info->defines[i].key; @@ -356,14 +357,14 @@ config_dump_full_stdout_callback(const struct config_export_setting *set, static void config_include_groups_dump(struct dump_context *ctx) { - uint32_t include_count_be32 = 0; + uint32_t include_count_32 = 0; if (ctx->include_groups == NULL) { - o_stream_nsend(ctx->output, &include_count_be32, - sizeof(include_count_be32)); + o_stream_nsend(ctx->output, &include_count_32, + sizeof(include_count_32)); } else { - include_count_be32 = cpu32_to_be(array_count(ctx->include_groups)); - o_stream_nsend(ctx->output, &include_count_be32, - sizeof(include_count_be32)); + include_count_32 = array_count(ctx->include_groups); + o_stream_nsend(ctx->output, &include_count_32, + sizeof(include_count_32)); const struct config_include_group *group; array_foreach(ctx->include_groups, group) { @@ -408,7 +409,7 @@ static void config_dump_full_callback(const struct config_export_setting *set, config_dump_full_write_filter(ctx); - uint32_t key_be32 = cpu32_to_be(set->key_define_idx); + uint32_t key_32 = set->key_define_idx; if (ctx->delayed_output != NULL && ((str_begins(set->key, "passdb", &suffix) && (suffix[0] == '\0' || suffix[0] == '/')) || @@ -416,12 +417,12 @@ static void config_dump_full_callback(const struct config_export_setting *set, (suffix[0] == '\0' || suffix[0] == '/')))) { /* For backwards compatibility: global passdbs and userdbs are added after per-protocol ones, not before. */ - str_append_data(ctx->delayed_output, &key_be32, - sizeof(key_be32)); + str_append_data(ctx->delayed_output, &key_32, + sizeof(key_32)); str_append_data(ctx->delayed_output, set->value, strlen(set->value)+1); } else { - o_stream_nsend(ctx->output, &key_be32, sizeof(key_be32)); + o_stream_nsend(ctx->output, &key_32, sizeof(key_32)); const struct setting_define *def = &ctx->info->defines[set->key_define_idx]; if (def->type == SET_STRLIST || def->type == SET_BOOLLIST) { @@ -496,7 +497,7 @@ config_dump_full_handle_error(struct dump_context *dump_ctx, } size_t error_len = strlen(error) + 1; - uint64_t blob_size = cpu64_to_be(error_len + 4); + uint64_t blob_size = error_len + 4; o_stream_nsend(output, &blob_size, sizeof(blob_size)); o_stream_nsend(output, error, error_len); uint32_t include_group_count = 0; @@ -515,8 +516,8 @@ struct config_dump_full_context { struct config_filter_parser *const *filters; uint32_t filter_output_count; - uint32_t *filter_indexes_be32; - uint64_t *filter_offsets_be64; + uint32_t *filter_indexes_32; + uint64_t *filter_offsets_64; }; enum config_dump_type { @@ -635,21 +636,20 @@ config_dump_full_sections(struct config_dump_full_context *ctx, } config_export_free(&export_ctx); if (dump_ctx.filter_written) { - ctx->filter_indexes_be32[ctx->filter_output_count] = - cpu32_to_be(i); - ctx->filter_offsets_be64[ctx->filter_output_count] = - cpu64_to_be(start_offset); + ctx->filter_indexes_32[ctx->filter_output_count] = i; + ctx->filter_offsets_64[ctx->filter_output_count] = + start_offset; ctx->filter_output_count++; } } if (delayed_filter != NULL && str_len(delayed_filter) > 0) { - ctx->filter_indexes_be32[ctx->filter_output_count] = + ctx->filter_indexes_32[ctx->filter_output_count] = 0; /* empty/global filter */ - ctx->filter_offsets_be64[ctx->filter_output_count] = - cpu64_to_be(output->offset); + ctx->filter_offsets_64[ctx->filter_output_count] = + output->offset; - uint64_t blob_size = cpu64_to_be(5 + str_len(delayed_filter)); + uint64_t blob_size = 5 + str_len(delayed_filter); o_stream_nsend(output, &blob_size, sizeof(blob_size)); o_stream_nsend(output, "", 1); /* no error */ uint32_t include_group_count = 0; @@ -780,8 +780,8 @@ int config_dump_full(struct config_parsed *config, uint32_t max_filter_count = 0; while (ctx.filters[max_filter_count] != NULL) max_filter_count++; - ctx.filter_indexes_be32 = t_new(uint32_t, max_filter_count); - ctx.filter_offsets_be64 = t_new(uint64_t, max_filter_count); + ctx.filter_indexes_32 = t_new(uint32_t, max_filter_count); + ctx.filter_offsets_64 = t_new(uint64_t, max_filter_count); ARRAY_TYPE(config_include_group) groups; t_array_init(&groups, 8); @@ -824,9 +824,9 @@ int config_dump_full(struct config_parsed *config, uoff_t blob_size_offset = output->offset; /* 2. Write global settings in config - use an empty filter */ - ctx.filter_indexes_be32[ctx.filter_output_count] = 0; - ctx.filter_offsets_be64[ctx.filter_output_count] = - cpu64_to_be(blob_size_offset); + ctx.filter_indexes_32[ctx.filter_output_count] = 0; + ctx.filter_offsets_64[ctx.filter_output_count] = + blob_size_offset; ctx.filter_output_count++; if (config_parsed_get_includes(config, filter_parser, @@ -887,18 +887,18 @@ int config_dump_full(struct config_parsed *config, break; if (dest != CONFIG_DUMP_FULL_DEST_STDOUT) { - o_stream_nsend(output, ctx.filter_indexes_be32, - sizeof(ctx.filter_indexes_be32[0]) * + o_stream_nsend(output, ctx.filter_indexes_32, + sizeof(ctx.filter_indexes_32[0]) * ctx.filter_output_count); - o_stream_nsend(output, ctx.filter_offsets_be64, - sizeof(ctx.filter_offsets_be64[0]) * + o_stream_nsend(output, ctx.filter_offsets_64, + sizeof(ctx.filter_offsets_64[0]) * ctx.filter_output_count); /* safety NUL at the end of the block */ o_stream_nsend(output, "", 1); } if (dest != CONFIG_DUMP_FULL_DEST_STDOUT) { - filter_count = cpu32_to_be(ctx.filter_output_count); + filter_count = ctx.filter_output_count; if (o_stream_pwrite(output, &filter_count, sizeof(filter_count), filter_count_offset) < 0) { diff --git a/src/lib-master/test-master-service-settings.c b/src/lib-master/test-master-service-settings.c index 51a7f6183e..87a259fd88 100644 --- a/src/lib-master/test-master-service-settings.c +++ b/src/lib-master/test-master-service-settings.c @@ -10,6 +10,15 @@ #define DATA(data) (const unsigned char *)data"\xff", sizeof(data"\xff")-2 +/* we only need to use 1 byte */ +#ifdef WORDS_BIGENDIAN +# define NUM64(n) "\x00\x00\x00\x00\x00\x00\x00"n +# define NUM32(n) "\x00\x00\x00"n +#else +# define NUM64(n) n"\x00\x00\x00\x00\x00\x00\x00" +# define NUM32(n) n"\x00\x00\x00" +#endif + static const struct { const unsigned char *data; size_t size; @@ -26,289 +35,289 @@ static const struct { /* full file size = 1, but file is still truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" // 19 bytes - "\x00\x00\x00\x00\x00\x00\x00\x01"), // full size + NUM64("\x01")), // full size "Full size mismatch" }, /* cache path count is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x04" // full size + NUM64("\x04") // full size "\x00\x00\x00"), // cache path count "Full size mismatch" }, /* event filter count is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x08" // full size - "\x00\x00\x00\x00" // cache path count + NUM64("\x08") // full size + NUM32("\x00") // cache path count "\x00\x00\x00"), // event filter count "Full size mismatch" }, /* event filter strings are truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x08" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x10\x00"), // event filter count + NUM64("\x08") // full size + NUM32("\x00") // cache path count + NUM32("\x01")), // event filter count "'filter string' points outside area" }, /* full file size is 7 bytes, which makes the first block size truncated, since it needs 8 bytes */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x11" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x11") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] "\x00\x00\x00\x00\x00\x00\x00"), // block size "Area too small when reading size of 'block size'" }, /* first block size is 0, which is too small */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x12" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x12") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x00"), // block size + NUM64("\x00")), // block size "'block name' points outside area" }, /* first block size is 1, but full file size is too small */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x12" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x12") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x01"), // block size + NUM64("\x01")), // block size "'block size' points outside are" }, /* block name is not NUL-terminated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x14" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x14") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x01" // block size + NUM64("\x01") // block size "N" "\x00"), // trailing garbage so we can have NUL "Settings block doesn't end with NUL at offset" }, /* settings count is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x17" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x17") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x05" // block size + NUM64("\x05") // block size "N\x00" // block name "\x00\x00\x00"), "Area too small when reading uint of 'settings count'" }, /* settings keys are truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x18" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x18") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x06" // block size + NUM64("\x06") // block size "N\x00" // block name - "\x00\x00\x01\x00"), // settings count + NUM32("\x01")), // settings count "'setting key' points outside area" }, /* filter count is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x1D" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x1D") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x0B" // block size + NUM64("\x0B") // block size "N\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key "\x00\x00\x00"), // filter count "Area too small when reading uint of 'filter count'" }, /* filter settings size is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x25" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x25") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x12" // block size + NUM64("\x12") // block size "N\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count + NUM32("\x01") // filter count "\x00\x00\x00\x00\x00\x00\x00"), // filter settings size "Area too small when reading size of 'filter settings size'" }, /* filter settings is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x26" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x26") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x14" // block size + NUM64("\x14") // block size "N\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x10\x00"), // filter settings size + NUM32("\x01") // filter count + NUM64("\x10")), // filter settings size "'filter settings size' points outside area" }, /* filter error is missing */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x33" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x33") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x21" // block size + NUM64("\x21") // block size "N\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings size - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x01") // filter count + NUM64("\x00") // filter settings size + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "'filter error string' points outside area" }, /* filter error is not NUL-terminated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x41" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x41") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x2F" // block size + NUM64("\x2F") // block size "master_service\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x01" // filter settings size + NUM32("\x01") // filter count + NUM64("\x01") // filter settings size "E" // filter error string - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "'filter error string' points outside area" }, /* include group count is truncated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x44" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x44") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x32" // block size + NUM64("\x32") // block size "master_service\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x04" // filter settings size + NUM32("\x01") // filter count + NUM64("\x04") // filter settings size "\x00" // filter error string "\x00\x00\x00" // include group count - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "Area too small when reading uint of 'include group count'" }, /* include group count is too large */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x45" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x45") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x33" // block size + NUM64("\x33") // block size "master_service\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x05" // filter settings size + NUM32("\x01") // filter count + NUM64("\x05") // filter settings size "\x00" // filter error string - "\x00\x00\x00\x01" // include group count - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x01") // include group count + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "'group label string' points outside area" }, /* group label not NUL-terminated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x46" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x46") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x34" // block size + NUM64("\x34") // block size "master_service\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x06" // filter settings size + NUM32("\x01") // filter count + NUM64("\x06") // filter settings size "\x00" // filter error string - "\x00\x00\x00\x01" // include group count + NUM32("\x01") // include group count "G" // group label - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "'group label string' points outside area" }, /* group name not NUL-terminated */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x48" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x48") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x36" // block size + NUM64("\x36") // block size "master_service\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x08" // filter settings size + NUM32("\x01") // filter count + NUM64("\x08") // filter settings size "\x00" // filter error string - "\x00\x00\x00\x01" // include group count + NUM32("\x01") // include group count "G\x00" // group label "N" // group name - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "'group name string' points outside area" }, /* invalid filter string */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x3A" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x3A") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "F\x00" // event filter[0] "F\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x26" // block size + NUM64("\x26") // block size "N\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x05" // filter settings size + NUM32("\x01") // filter count + NUM64("\x05") // filter settings size "\x00" // filter error string - "\x00\x00\x00\x00" // include group count - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x00") // include group count + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00"), // safety NUL "Received invalid filter 'F' at index 0: event filter: syntax error" }, /* Duplicate block name */ { DATA("DOVECOT-CONFIG\t1.0\n" - "\x00\x00\x00\x00\x00\x00\x00\x42" // full size - "\x00\x00\x00\x00" // cache path count - "\x00\x00\x00\x01" // event filter count + NUM64("\x42") // full size + NUM32("\x00") // cache path count + NUM32("\x01") // event filter count "\x00" // event filter[0] "\x00" // override event filter[0] - "\x00\x00\x00\x00\x00\x00\x00\x26" // block size + NUM64("\x26") // block size "N\x00" // block name - "\x00\x00\x00\x01" // settings count + NUM32("\x01") // settings count "K\x00" // setting[0] key - "\x00\x00\x00\x01" // filter count - "\x00\x00\x00\x00\x00\x00\x00\x05" // filter settings size + NUM32("\x01") // filter count + NUM64("\x05") // filter settings size "\x00" // filter error string - "\x00\x00\x00\x00" // include group count - "\x00\x00\x00\x00" // event filter index - "\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings offset + NUM32("\x00") // include group count + NUM32("\x00") // event filter index + NUM64("\x00") // filter settings offset "\x00" // safety NUL - "\x00\x00\x00\x00\x00\x00\x00\x02" // 2nd block size + NUM64("\x02") // 2nd block size "N\x00"), // 2nd block name "Duplicate block name 'N'" }, }; diff --git a/src/lib-settings/settings.c b/src/lib-settings/settings.c index fcf90c08ec..80526dc6ae 100644 --- a/src/lib-settings/settings.c +++ b/src/lib-settings/settings.c @@ -224,7 +224,8 @@ settings_block_read_uint64(struct settings_mmap *mmap, *offset, end_offset, mmap->mmap_size); return -1; } - *num_r = be64_to_cpu_unaligned(CONST_PTR_OFFSET(mmap->mmap_base, *offset)); + memcpy(num_r, CONST_PTR_OFFSET(mmap->mmap_base, *offset), + sizeof(*num_r)); *offset += sizeof(*num_r); return 0; } @@ -242,7 +243,8 @@ settings_block_read_uint32(struct settings_mmap *mmap, *offset, end_offset, mmap->mmap_size); return -1; } - *num_r = be32_to_cpu_unaligned(CONST_PTR_OFFSET(mmap->mmap_base, *offset)); + memcpy(num_r, CONST_PTR_OFFSET(mmap->mmap_base, *offset), + sizeof(*num_r)); *offset += sizeof(*num_r); return 0; } @@ -260,7 +262,8 @@ settings_block_read_size(struct settings_mmap *mmap, *offset, end_offset, mmap->mmap_size); return -1; } - *size_r = be64_to_cpu_unaligned(CONST_PTR_OFFSET(mmap->mmap_base, *offset)); + memcpy(size_r, CONST_PTR_OFFSET(mmap->mmap_base, *offset), + sizeof(*size_r)); if (*size_r > end_offset - *offset - sizeof(*size_r)) { *error_r = t_strdup_printf( "'%s' points outside area " @@ -697,8 +700,9 @@ settings_mmap_parse(struct settings_mmap *mmap, const char *service_name, /* */ size_t full_size_offset = eol - mmap_base + 1; - uint64_t settings_full_size = - be64_to_cpu_unaligned(mmap_base + full_size_offset); + uint64_t settings_full_size; + memcpy(&settings_full_size, mmap_base + full_size_offset, + sizeof(settings_full_size)); if (full_size_offset + sizeof(settings_full_size) + settings_full_size != mmap_size) { *error_r = t_strdup_printf("Full size mismatch: " @@ -958,8 +962,9 @@ settings_mmap_apply_blob(struct settings_apply_ctx *ctx, while (offset < end_offset) { /* We already checked that settings blob ends with NUL, so strlen() can be used safely. */ - uint32_t key_idx = be32_to_cpu_unaligned( - CONST_PTR_OFFSET(mmap->mmap_base, offset)); + uint32_t key_idx; + memcpy(&key_idx, CONST_PTR_OFFSET(mmap->mmap_base, offset), + sizeof(key_idx)); if (key_idx >= block->settings_count) { *error_r = t_strdup_printf( "Settings key index too high (%u >= %u)", @@ -1086,10 +1091,13 @@ settings_mmap_get_filter_idx(struct settings_mmap *mmap, uint32_t filter_idx, uint32_t *event_filter_idx_r, const char **error_r) { - uint32_t event_filter_idx = be32_to_cpu_unaligned( - CONST_PTR_OFFSET(mmap->mmap_base, - block->filter_indexes_start_offset + - sizeof(uint32_t) * filter_idx)); + uint32_t event_filter_idx; + + memcpy(&event_filter_idx, + CONST_PTR_OFFSET(mmap->mmap_base, + block->filter_indexes_start_offset + + sizeof(uint32_t) * filter_idx), + sizeof(event_filter_idx)); if (event_filter_idx >= mmap->event_filters_count) { *error_r = t_strdup_printf("event filter idx %u >= %u", event_filter_idx, mmap->event_filters_count); @@ -1107,12 +1115,15 @@ static int settings_mmap_apply_filter(struct settings_apply_ctx *ctx, const char **error_r) { struct settings_mmap *mmap = ctx->instance->mmap; - uint64_t filter_offset = be64_to_cpu_unaligned( - CONST_PTR_OFFSET(mmap->mmap_base, - block->filter_offsets_start_offset + - sizeof(uint64_t) * filter_idx)); - uint64_t filter_set_size = be64_to_cpu_unaligned( - CONST_PTR_OFFSET(mmap->mmap_base, filter_offset)); + uint64_t filter_offset, filter_set_size; + memcpy(&filter_offset, + CONST_PTR_OFFSET(mmap->mmap_base, + block->filter_offsets_start_offset + + sizeof(uint64_t) * filter_idx), + sizeof(filter_offset)); + memcpy(&filter_set_size, + CONST_PTR_OFFSET(mmap->mmap_base, filter_offset), + sizeof(filter_set_size)); filter_offset += sizeof(filter_set_size); uint64_t filter_end_offset = filter_offset + filter_set_size; @@ -1124,8 +1135,9 @@ static int settings_mmap_apply_filter(struct settings_apply_ctx *ctx, } filter_offset += strlen(filter_error) + 1; - uint32_t include_count = be32_to_cpu_unaligned( - CONST_PTR_OFFSET(mmap->mmap_base, filter_offset)); + uint32_t include_count; + memcpy(&include_count, CONST_PTR_OFFSET(mmap->mmap_base, filter_offset), + sizeof(include_count)); filter_offset += sizeof(include_count); if (ctx->filter_name != NULL && !ctx->seen_filter &&