Browse Source

features: have clear_feature_bit correctly resize bitfield

There's a spec rule about only ever sending a correctly sized
feature-bits, so as a precaution we have `clear_feature_bit` correctly
resize when a bit is cleared.
travis-experimental
niftynei 4 years ago
committed by neil saitug
parent
commit
0871bf0999
  1. 16
      common/features.c
  2. 34
      common/test/run-features.c

16
common/features.c

@ -121,6 +121,21 @@ static const struct dependency feature_deps[] = {
#endif #endif
}; };
static void trim_features(u8 **features)
{
size_t trim, len = tal_bytelen(*features);
/* Don't try to tal_resize a NULL array */
if (len == 0)
return;
/* Big-endian bitfields are weird, but it means we trim
* from the front: */
for (trim = 0; trim < len && (*features)[trim] == 0; trim++);
memmove(*features, *features + trim, len - trim);
tal_resize(features, len - trim);
}
static void clear_feature_bit(u8 *features, u32 bit) static void clear_feature_bit(u8 *features, u32 bit)
{ {
size_t bytenum = bit / 8, bitnum = bit % 8, len = tal_count(features); size_t bytenum = bit / 8, bitnum = bit % 8, len = tal_count(features);
@ -234,6 +249,7 @@ u8 *get_agreed_channelfeatures(const tal_t *ctx,
if (!feature_offered(their_features, i)) { if (!feature_offered(their_features, i)) {
clear_feature_bit(f, COMPULSORY_FEATURE(i)); clear_feature_bit(f, COMPULSORY_FEATURE(i));
clear_feature_bit(f, OPTIONAL_FEATURE(i)); clear_feature_bit(f, OPTIONAL_FEATURE(i));
trim_features(&f);
continue; continue;
} }
max_len = (i / 8) + 1; max_len = (i / 8) + 1;

34
common/test/run-features.c

@ -179,6 +179,39 @@ static void test_feature_set_or(void)
} }
} }
static void test_feature_trim(void)
{
struct feature_set *f;
for (size_t i = 0; i < ARRAY_SIZE(f->bits); i++) {
f = talz(tmpctx, struct feature_set);
f->bits[i] = tal_arr(f, u8, 0);
set_feature_bit(&f->bits[i], 255);
assert(tal_bytelen(f->bits[i]) == 32);
clear_feature_bit(f->bits[i], 255);
trim_features(&f->bits[i]);
assert(tal_bytelen(f->bits[i]) == 0);
set_feature_bit(&f->bits[i], 7);
assert(tal_bytelen(f->bits[i]) == 1);
set_feature_bit(&f->bits[i], 255);
assert(tal_bytelen(f->bits[i]) == 32);
clear_feature_bit(f->bits[i], 255);
trim_features(&f->bits[i]);
assert(tal_bytelen(f->bits[i]) == 1);
clear_feature_bit(f->bits[i], 7);
trim_features(&f->bits[i]);
assert(tal_bytelen(f->bits[i]) == 0);
set_feature_bit(&f->bits[i], 8);
set_feature_bit(&f->bits[i], 10);
assert(tal_bytelen(f->bits[i]) == 2);
clear_feature_bit(f->bits[i], 10);
trim_features(&f->bits[i]);
assert(tal_bytelen(f->bits[i]) == 2);
}
}
int main(void) int main(void)
{ {
u8 *bits; u8 *bits;
@ -265,6 +298,7 @@ int main(void)
test_featurebits_or(); test_featurebits_or();
test_feature_set_or(); test_feature_set_or();
test_feature_trim();
wally_cleanup(0); wally_cleanup(0);
tal_free(tmpctx); tal_free(tmpctx);

Loading…
Cancel
Save