mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 08:25:20 +08:00
[Bug #22458] Fix out-of-bound in Time#strftime
This commit is contained in:
2 files changed
+28
-16
Notes:
git
2026-10-21 11:53:54 +00:00
No files matched your search
+21
-16
@@ -173,11 +173,15 @@ resize_buffer(VALUE ftime, char *s, const char **start, const char **endp,
|
||||
size_t len = s - *start;
|
||||
size_t need = len + n * 2;
|
||||
size_t nlen = rb_str_capacity(ftime);
|
||||
while (nlen < need) nlen <<= 1;
|
||||
|
||||
if (nlen < len || nlen > maxsize) {
|
||||
return 0;
|
||||
if (nlen > maxsize) return 0;
|
||||
while (nlen < need) {
|
||||
nlen <<= 1;
|
||||
if (nlen < len || nlen > maxsize) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rb_str_set_len(ftime, len);
|
||||
rb_str_modify_expand(ftime, nlen-len);
|
||||
s = RSTRING_PTR(ftime);
|
||||
@@ -548,34 +552,35 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
|
||||
else {
|
||||
sign = +1;
|
||||
}
|
||||
switch (colons) {
|
||||
#define NEEDS_FOR_ZONE(fmt) do { \
|
||||
const int zone_size = rb_strlen_lit(fmt); \
|
||||
if (precision < zone_size) precision = zone_size; \
|
||||
NEEDS(precision); \
|
||||
precision -= zone_size - rb_strlen_lit("hh"); \
|
||||
} while (0)
|
||||
|
||||
switch (colons) {
|
||||
case 0: /* %z -> +hhmm */
|
||||
precision = precision <= 5 ? 2 : precision-3;
|
||||
NEEDS(precision + 3);
|
||||
NEEDS_FOR_ZONE("+hhmm");
|
||||
break;
|
||||
|
||||
case 1: /* %:z -> +hh:mm */
|
||||
precision = precision <= 6 ? 2 : precision-4;
|
||||
NEEDS(precision + 4);
|
||||
NEEDS_FOR_ZONE("+hh:mm");
|
||||
break;
|
||||
|
||||
case 2: /* %::z -> +hh:mm:ss */
|
||||
precision = precision <= 9 ? 2 : precision-7;
|
||||
NEEDS(precision + 7);
|
||||
NEEDS_FOR_ZONE("+hh:mm:ss");
|
||||
break;
|
||||
|
||||
case 3: /* %:::z -> +hh[:mm[:ss]] */
|
||||
if (off % 3600 == 0) {
|
||||
precision = precision <= 3 ? 2 : precision-1;
|
||||
NEEDS(precision + 3);
|
||||
NEEDS_FOR_ZONE("+hh");
|
||||
}
|
||||
else if (off % 60 == 0) {
|
||||
precision = precision <= 6 ? 2 : precision-4;
|
||||
NEEDS(precision + 4);
|
||||
NEEDS_FOR_ZONE("+hh:mm");
|
||||
}
|
||||
else {
|
||||
precision = precision <= 9 ? 2 : precision-7;
|
||||
NEEDS(precision + 9);
|
||||
NEEDS_FOR_ZONE("+hh:mm:ss");
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ require 'test/unit'
|
||||
require 'delegate'
|
||||
require 'timeout'
|
||||
require 'delegate'
|
||||
require 'rbconfig/sizeof'
|
||||
|
||||
class TestTime < Test::Unit::TestCase
|
||||
def setup
|
||||
@@ -1114,6 +1115,12 @@ class TestTime < Test::Unit::TestCase
|
||||
assert_equal(" -0:55:00", t.strftime("%_10::z"), bug6323)
|
||||
assert_equal("-000:55:00", t.strftime("%10::z"), bug6323)
|
||||
assert_equal("-000000:55", t.strftime("%10:::z"))
|
||||
|
||||
t = Time.at(0, in: 0)
|
||||
max = RbConfig::LIMITS["INT_MAX"]
|
||||
all_assertions_foreach(nil, *%W[%#{max}z %#{max}:z %#{max}::z %#{max}:::z]) do |z|
|
||||
assert_raise(Errno::ERANGE) {t.strftime(z)}
|
||||
end
|
||||
end
|
||||
|
||||
def test_strftime_invalid_modifier
|
||||
|
||||
Reference in new issue
Block a user