Skip to content

Commit e9e872b

Browse files
msgpack: fix decoding intervals with int64
It is possible for interval to have days, hours, minutes and seconds larger than INT_MAX (or less than INT_MIN). Before this patch, msgpack decoding had failed to parse intervals with msgpack int64 and uint64. int64_t should be enough to store any value allowed for datetime intervals. Closes tarantool#8887 NO_DOC=small bug fix
1 parent 56488e1 commit e9e872b

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## bugfix/msgpack
2+
3+
* Fixed decoding datetime intervals with fields larger than possible int32
4+
values (gh-8887).

src/lib/core/mp_interval.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ interval_unpack(const char **data, uint32_t len, struct interval *itv)
116116
memset(itv, 0, sizeof(*itv));
117117
for (uint32_t i = 0; i < count; ++i) {
118118
uint32_t field = mp_load_u8(data);
119-
int32_t value;
119+
int64_t value;
120120
enum mp_type type = mp_typeof(**data);
121121
if (type == MP_UINT) {
122122
if (mp_check_uint(*data, end) > 0)
@@ -127,7 +127,7 @@ interval_unpack(const char **data, uint32_t len, struct interval *itv)
127127
} else {
128128
return NULL;
129129
}
130-
if (mp_read_int32(data, &value) != 0)
130+
if (mp_read_int64(data, &value) != 0)
131131
return NULL;
132132
switch (field) {
133133
case FIELD_YEAR:
@@ -155,7 +155,7 @@ interval_unpack(const char **data, uint32_t len, struct interval *itv)
155155
itv->nsec = value;
156156
break;
157157
case FIELD_ADJUST:
158-
if (value > (int32_t)DT_SNAP)
158+
if (value > (int64_t)DT_SNAP)
159159
return NULL;
160160
itv->adjust = (dt_adjust_t)value;
161161
break;

test/unit/interval.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,62 @@ test_interval_encode_decode(void)
9696
is(result.adjust, DT_EXCESS, "Adjust value is right");
9797
}
9898

99+
static void
100+
test_interval_encode_decode_limits(void)
101+
{
102+
struct interval itv;
103+
memset(&itv, 0, sizeof(itv));
104+
struct interval result;
105+
interval_mp_recode(&itv, &result);
106+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
107+
108+
itv.day = -4295055470;
109+
interval_mp_recode(&itv, &result);
110+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
111+
112+
itv.day = 4295055470;
113+
interval_mp_recode(&itv, &result);
114+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
115+
116+
itv.hour = -103081331286;
117+
interval_mp_recode(&itv, &result);
118+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
119+
120+
itv.hour = 103081331286;
121+
interval_mp_recode(&itv, &result);
122+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
123+
124+
itv.min = -6184879877160;
125+
interval_mp_recode(&itv, &result);
126+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
127+
128+
itv.min = 6184879877160;
129+
interval_mp_recode(&itv, &result);
130+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
131+
132+
itv.sec = -371092792629600;
133+
interval_mp_recode(&itv, &result);
134+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
135+
136+
itv.sec = 371092792629600;
137+
interval_mp_recode(&itv, &result);
138+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
139+
140+
itv.nsec = -2147483647;
141+
interval_mp_recode(&itv, &result);
142+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
143+
144+
itv.nsec = 2147483647;
145+
interval_mp_recode(&itv, &result);
146+
ok(is_interval_equal(&itv, &result), "Intervals are equal.");
147+
}
148+
99149
int
100150
main(void)
101151
{
102-
plan(21);
152+
plan(32);
103153
test_interval_sizeof();
104154
test_interval_encode_decode();
155+
test_interval_encode_decode_limits();
105156
return check_plan();
106157
}

0 commit comments

Comments
 (0)