Avoid using nested zero-sized arrays to allow compilation with MSVC. Also, make sure the immediate data is accessed only if it exists, and that the size is always calculated from struct learn_spec field 'n_bits'.
Reported-by: Alin Serdean <aserd...@cloudbasesolutions.com> Signed-off-by: Jarno Rajahalme <ja...@ovn.org> --- include/openvswitch/ofp-actions.h | 39 +++++++++++++++++++++++---------------- lib/learn.c | 16 ++++++++++------ lib/ofp-actions.c | 5 +++-- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h index e92b413..bf7d62f 100644 --- a/include/openvswitch/ofp-actions.h +++ b/include/openvswitch/ofp-actions.h @@ -708,29 +708,36 @@ enum nx_learn_flags { /* Part of struct ofpact_learn, below. */ struct ofpact_learn_spec { - struct mf_subfield src; /* NX_LEARN_SRC_FIELD only. */ - struct mf_subfield dst; /* NX_LEARN_DST_MATCH, NX_LEARN_DST_LOAD only. */ - uint16_t src_type; /* One of NX_LEARN_SRC_*. */ - uint16_t dst_type; /* One of NX_LEARN_DST_*. */ - uint8_t n_bits; /* Number of bits in source and dest. */ - uint64_t src_imm[]; /* OFPACT_ALIGNTO (uint64_t) aligned. */ + OFPACT_PADDED_MEMBERS( + struct mf_subfield src; /* NX_LEARN_SRC_FIELD only. */ + struct mf_subfield dst; /* NX_LEARN_DST_MATCH, + * NX_LEARN_DST_LOAD only. */ + uint16_t src_type; /* One of NX_LEARN_SRC_*. */ + uint16_t dst_type; /* One of NX_LEARN_DST_*. */ + uint8_t n_bits; /* Number of bits in source and dest. */ + ); + /* Followed by 'DIV_ROUND_UP(n_bits, 8)' bytes of immediate data for + * match 'dst_type's NX_LEARN_DST_MATCH and NX_LEARN_DST_LOAD when + * NX_LEARN_SRC_IMMEDIATE is set in 'src_type', followed by zeroes to align + * to OFPACT_ALIGNTO. */ }; -BUILD_ASSERT_DECL(offsetof(struct ofpact_learn_spec, src_imm) - % OFPACT_ALIGNTO == 0); -BUILD_ASSERT_DECL(offsetof(struct ofpact_learn_spec, src_imm) - == sizeof(struct ofpact_learn_spec)); +BUILD_ASSERT_DECL(sizeof(struct ofpact_learn_spec) % OFPACT_ALIGNTO == 0); + +static inline const void * +ofpact_learn_spec_imm(const struct ofpact_learn_spec *spec) +{ + return spec + 1; +} static inline const struct ofpact_learn_spec * ofpact_learn_spec_next(const struct ofpact_learn_spec *spec) { if (spec->src_type == NX_LEARN_SRC_IMMEDIATE) { - unsigned int n_uint64s - = OFPACT_ALIGN(DIV_ROUND_UP(spec->n_bits, 8)) / sizeof (uint64_t); - return (const struct ofpact_learn_spec *) - ((const uint64_t *)(spec + 1) + n_uint64s); - } else { - return spec + 1; + unsigned int n_bytes = OFPACT_ALIGN(DIV_ROUND_UP(spec->n_bits, 8)); + return ALIGNED_CAST(const struct ofpact_learn_spec *, + (const uint8_t *)(spec + 1) + n_bytes); } + return spec + 1; } /* OFPACT_LEARN. diff --git a/lib/learn.c b/lib/learn.c index 2d057d4..bb57f7d 100644 --- a/lib/learn.c +++ b/lib/learn.c @@ -60,7 +60,10 @@ learn_check(const struct ofpact_learn *learn, const struct flow *flow) if (error) { return error; } - mf_write_subfield_value(&spec->dst, spec->src_imm, &match); + if (spec->src_type & NX_LEARN_SRC_IMMEDIATE) { + mf_write_subfield_value(&spec->dst, + ofpact_learn_spec_imm(spec), &match); + } break; case NX_LEARN_DST_LOAD: @@ -128,7 +131,8 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow, if (spec->src_type == NX_LEARN_SRC_FIELD) { mf_read_subfield(&spec->src, flow, &value); } else { - mf_subvalue_from_value(&spec->dst, &value, spec->src_imm); + mf_subvalue_from_value(&spec->dst, &value, + ofpact_learn_spec_imm(spec)); } switch (spec->dst_type) { @@ -457,7 +461,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s) for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec = ofpact_learn_spec_next(spec)) { - unsigned int n_bytes = DIV_ROUND_UP(spec->dst.n_bits, 8); + unsigned int n_bytes = DIV_ROUND_UP(spec->n_bits, 8); ds_put_char(s, ','); switch (spec->src_type | spec->dst_type) { @@ -468,7 +472,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s) memset(&value, 0, sizeof value); memcpy(&value.b[spec->dst.field->n_bytes - n_bytes], - spec->src_imm, n_bytes); + ofpact_learn_spec_imm(spec), n_bytes); ds_put_format(s, "%s%s=%s", colors.param, spec->dst.field->name, colors.end); mf_format(spec->dst.field, &value, NULL, s); @@ -476,7 +480,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s) ds_put_format(s, "%s", colors.param); mf_format_subfield(&spec->dst, s); ds_put_format(s, "=%s", colors.end); - ds_put_hex(s, spec->src_imm, n_bytes); + ds_put_hex(s, ofpact_learn_spec_imm(spec), n_bytes); } break; } @@ -493,7 +497,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s) case NX_LEARN_SRC_IMMEDIATE | NX_LEARN_DST_LOAD: ds_put_format(s, "%sload:%s", colors.special, colors.end); - ds_put_hex(s, spec->src_imm, n_bytes); + ds_put_hex(s, ofpact_learn_spec_imm(spec), n_bytes); ds_put_format(s, "%s->%s", colors.special, colors.end); mf_format_subfield(&spec->dst, s); break; diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 1dd5356..f27ff21 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -4431,9 +4431,10 @@ encode_LEARN(const struct ofpact_learn *learn, } else { size_t n_dst_bytes = 2 * DIV_ROUND_UP(spec->n_bits, 16); uint8_t *bits = ofpbuf_put_zeros(out, n_dst_bytes); - unsigned int n_bytes = DIV_ROUND_UP(spec->dst.n_bits, 8); + unsigned int n_bytes = DIV_ROUND_UP(spec->n_bits, 8); - memcpy(bits + n_dst_bytes - n_bytes, spec->src_imm, n_bytes); + memcpy(bits + n_dst_bytes - n_bytes, ofpact_learn_spec_imm(spec), + n_bytes); } if (spec->dst_type == NX_LEARN_DST_MATCH || -- 2.1.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev