Skip to content

Commit

Permalink
ames: account for variable-size num fragments (#561)
Browse files Browse the repository at this point in the history
Currently we assume that the number of fragments in a `meow` has a fixed
size of 4 bytes (which is also how we deserialize meows in in
[lull.hoon](https://github.com/urbit/urbit/blob/develop/pkg/arvo/sys/lull.hoon#L1397);
see `+sift-meow`), but in some cases we will retrieve from the cache a
meow that has less than 4 bytes, which means that we will go over the
actual length of the meow when calculating the size of the response to
be sent.

(To reproduce the problem, [this pdf](https://www.lab6.com/0) will cause
the publisher to crash on the last fragment if anybody requests it using
remote scry)

This PR fixes this by checking how many bytes are actually used in a
word, and then using that information to correctly calculate the size of
the `meow`.

Thanks to @pkova and @joemfb for helping with this.
  • Loading branch information
pkova authored Dec 4, 2023
2 parents 65f03b3 + abb1599 commit 3d93dc2
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions pkg/vere/io/ames.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
typedef struct _u3_meow {
c3_y sig_y[64]; // host signature
c3_w num_w; // number of fragments
c3_w siz_s; // datum size (actual)
c3_s siz_s; // datum size (actual)
c3_y* dat_y; // datum (0 if null response)
} u3_meow;

Expand Down Expand Up @@ -358,12 +358,25 @@ _fine_peep_size(u3_peep* pep_u)
pep_u->len_s);
}

static inline c3_y
_fine_bytes_word(c3_w num_w)
{
return (c3_bits_word(num_w) + 7) >> 3;
}

static inline c3_s
_fine_meow_size(u3_meow* mew_u)
{
c3_y cur_y = 0;
if (mew_u->siz_s != 0) {
cur_y = sizeof(mew_u->num_w);
}
else {
cur_y = _fine_bytes_word(mew_u->num_w);
}
return (
sizeof(mew_u->sig_y) +
sizeof(mew_u->num_w) +
cur_y +
mew_u->siz_s);
}

Expand Down Expand Up @@ -603,7 +616,9 @@ _fine_sift_meow(u3_meow* mew_u, u3_noun mew)
// parse number of fragments
//
u3r_bytes(cur_w, num_w, (c3_y*)&mew_u->num_w, mew);
num_w = c3_min(num_w, (len_w - cur_w));
cur_w += num_w;
u3_assert(len_w >= cur_w);

// parse data payload
//
Expand Down Expand Up @@ -735,10 +750,22 @@ _fine_etch_meow(u3_meow* mew_u, c3_y* buf_y)
memcpy(buf_y + cur_w, mew_u->sig_y, sig_w);
cur_w += sig_w;

// write number of fragments
//
_ames_etch_word(buf_y + cur_w, mew_u->num_w);
cur_w += sizeof(mew_u->num_w);
{
c3_y num_y[4];
c3_y len_y = _fine_bytes_word(mew_u->num_w);

// write number of fragments
//
_ames_etch_word(num_y, mew_u->num_w);
memcpy(buf_y + cur_w, num_y, len_y);

if (mew_u->siz_s != 0) {
cur_w += sizeof(mew_u->num_w);
}
else {
cur_w += len_y;
}
}

// write response fragment data
//
Expand Down

0 comments on commit 3d93dc2

Please sign in to comment.