summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-03-01 07:56:11 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-03-01 07:58:14 +0900
commit65add8c650088f398642aa9611baf4cb2266fff4 (patch)
tree2acfc48a9e1322d68aecef15f73ef650e1552e80
parenteb68adafa1d28ac6adc78057624ba315d7fe2790 (diff)
downloadmruby-65add8c650088f398642aa9611baf4cb2266fff4.tar.gz
mruby-65add8c650088f398642aa9611baf4cb2266fff4.zip
time.c: avoid using `mrb_int_{add,sub}_overflow()`.
The size and signedness of `mrb_int` and `time_t` may differ.
-rw-r--r--mrbgems/mruby-time/src/time.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index 0a8b30233..fcd5902e0 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -556,6 +556,12 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self)
return mrb_fixnum_value(0);
}
+static mrb_noreturn void
+int_overflow(mrb_state *mrb, const char *reason)
+{
+ mrb_raisef(mrb, E_RANGE_ERROR, "time_t overflow in Time %s", reason);
+}
+
static mrb_value
mrb_time_plus(mrb_state *mrb, mrb_value self)
{
@@ -565,9 +571,22 @@ mrb_time_plus(mrb_state *mrb, mrb_value self)
tm = time_get_ptr(mrb, self);
sec = mrb_to_time_t(mrb, o, &usec);
- if (mrb_int_add_overflow(tm->sec, sec, &sec)) {
- mrb_raise(mrb, E_RANGE_ERROR, "time_t overflow in Time");
+#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
+ if (__builtin_add_overflow(tm->sec, sec, &sec)) {
+ int_overflow(mrb, "addition");
+ }
+#else
+ if (sec >= 0) {
+ if (tm->sec > MRB_TIME_MAX - sec) {
+ int_overflow(mrb, "addition");
+ }
+ }
+ else {
+ if (tm->sec < MRB_TIME_MIN - sec) {
+ int_overflow(mrb, "addition");
+ }
}
+#endif
return mrb_time_make_time(mrb, mrb_obj_class(mrb, self), sec, tm->usec+usec, tm->timezone);
}
@@ -595,9 +614,22 @@ mrb_time_minus(mrb_state *mrb, mrb_value self)
else {
time_t sec, usec;
sec = mrb_to_time_t(mrb, other, &usec);
- if (mrb_int_sub_overflow(tm->sec, sec, &sec)) {
- mrb_raise(mrb, E_RANGE_ERROR, "time_t overflow in Time");
+#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
+ if (__builtin_sub_overflow(tm->sec, sec, &sec)) {
+ int_overflow(mrb, "subtraction");
+ }
+#else
+ if (sec >= 0) {
+ if (tm->sec < MRB_TIME_MIN + sec) {
+ int_overflow(mrb, "subtraction");
+ }
}
+ else {
+ if (tm->sec > MRB_TIME_MAX + sec) {
+ int_overflow(mrb, "subtraction");
+ }
+ }
+#endif
return mrb_time_make_time(mrb, mrb_obj_class(mrb, self), sec, tm->usec-usec, tm->timezone);
}
}