[PATCH 3/8] Add 'exact_field_count' parameter to options decoder
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Wed Aug 8 01:03:46 MSK 2018
Needed for promotion. Promotion uses system space
_promotion, into which a user can write tuples directly
with not API usage (and we can not do anything with it),
so _promotion should do severe validation of each field
of each tuple since it affects the cluster state.
For this a new parameter of options decoder is introduced,
that checks for exact field count.
Needed for #3055
---
src/box/alter.cc | 10 +++++-----
src/box/key_def.c | 2 +-
src/box/opt_def.c | 13 ++++++++-----
src/box/opt_def.h | 16 +++++++++++++++-
4 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 3007a131d..d13ecb783 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -239,7 +239,7 @@ index_opts_decode(struct index_opts *opts, const char *map)
{
index_opts_create(opts);
if (opts_decode(opts, index_opts_reg, &map, ER_WRONG_INDEX_OPTIONS,
- BOX_INDEX_FIELD_OPTS, NULL) != 0)
+ BOX_INDEX_FIELD_OPTS, NULL, 0) != 0)
diag_raise();
if (opts->distance == rtree_index_distance_type_MAX) {
tnt_raise(ClientError, ER_WRONG_INDEX_OPTIONS,
@@ -403,8 +403,8 @@ space_opts_decode(struct space_opts *opts, const char *data)
flags++;
}
} else if (opts_decode(opts, space_opts_reg, &data,
- ER_WRONG_SPACE_OPTIONS,
- BOX_SPACE_FIELD_OPTS, NULL) != 0) {
+ ER_WRONG_SPACE_OPTIONS, BOX_SPACE_FIELD_OPTS,
+ NULL, 0) != 0) {
diag_raise();
}
}
@@ -2382,8 +2382,8 @@ coll_id_def_new_from_tuple(const struct tuple *tuple, struct coll_id_def *def)
assert(base->type == COLL_TYPE_ICU);
if (opts_decode(&base->icu, coll_icu_opts_reg, &options,
- ER_WRONG_COLLATION_OPTIONS,
- BOX_COLLATION_FIELD_OPTIONS, NULL) != 0)
+ ER_WRONG_COLLATION_OPTIONS, BOX_COLLATION_FIELD_OPTIONS,
+ NULL, 0) != 0)
diag_raise();
if (base->icu.french_collation == coll_icu_on_off_MAX) {
diff --git a/src/box/key_def.c b/src/box/key_def.c
index ee09dc99d..bc0c1ba35 100644
--- a/src/box/key_def.c
+++ b/src/box/key_def.c
@@ -454,7 +454,7 @@ key_def_decode_parts(struct key_part_def *parts, uint32_t part_count,
*part = key_part_def_default;
if (opts_decode(part, part_def_reg, data,
ER_WRONG_INDEX_OPTIONS, i + TUPLE_INDEX_BASE,
- NULL) != 0)
+ NULL, 0) != 0)
return -1;
if (part->type == field_type_MAX) {
diag_set(ClientError, ER_WRONG_INDEX_OPTIONS,
diff --git a/src/box/opt_def.c b/src/box/opt_def.c
index cd93c23b8..6710f8187 100644
--- a/src/box/opt_def.c
+++ b/src/box/opt_def.c
@@ -176,13 +176,10 @@ opts_parse_key(void *opts, const struct opt_def *reg, const char *key,
return 0;
}
-/**
- * Populate key options from their msgpack-encoded representation
- * (msgpack map).
- */
int
opts_decode(void *opts, const struct opt_def *reg, const char **map,
- uint32_t errcode, uint32_t field_no, struct region *region)
+ uint32_t errcode, uint32_t field_no, struct region *region,
+ uint32_t exact_field_count)
{
assert(mp_typeof(**map) == MP_MAP);
@@ -191,6 +188,12 @@ opts_decode(void *opts, const struct opt_def *reg, const char **map,
* DDL is not performance-critical, so this is not a problem.
*/
uint32_t map_size = mp_decode_map(map);
+ if (map_size != exact_field_count && exact_field_count != 0) {
+ diag_set(ClientError, errcode, field_no,
+ tt_sprintf("expected %u keys but got %u",
+ exact_field_count, map_size));
+ return -1;
+ }
for (uint32_t i = 0; i < map_size; i++) {
if (mp_typeof(**map) != MP_STR) {
diag_set(ClientError, errcode, field_no,
diff --git a/src/box/opt_def.h b/src/box/opt_def.h
index 633832af9..4cfebf62a 100644
--- a/src/box/opt_def.h
+++ b/src/box/opt_def.h
@@ -83,10 +83,24 @@ struct region;
/**
* Populate key options from their msgpack-encoded representation
* (msgpack map).
+ * @param[out] opts Where decode options to.
+ * @param reg Field definitions array.
+ * @param map MessagePack to decode.
+ * @param errcode Error code to set on any error. The error code
+ * has to accept field number and description as
+ * parameters.
+ * @param field_no Field number to set for @a errcode.
+ * @param region Region for dynamic allocations such as strings.
+ * @param exact_field_count If non-zero, then @a map should
+ * contain exactly this count of fields.
+ *
+ * @retval 0 Success.
+ * @retval -1 Error.
*/
int
opts_decode(void *opts, const struct opt_def *reg, const char **map,
- uint32_t errcode, uint32_t field_no, struct region *region);
+ uint32_t errcode, uint32_t field_no, struct region *region,
+ uint32_t exact_field_count);
/**
* Decode one option and store it into @a opts struct as a field.
--
2.15.2 (Apple Git-101.1)
More information about the Tarantool-patches
mailing list