summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/date/date_core.c4
-rw-r--r--ext/date/date_strptime.c6
-rw-r--r--ext/json/generator/generator.c19
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/parser.c58
-rw-r--r--ext/objspace/objspace_dump.c2
-rw-r--r--ext/openssl/lib/openssl/digest.rb24
-rw-r--r--ext/openssl/ossl_kdf.c8
-rw-r--r--ext/openssl/ossl_pkcs12.c11
-rw-r--r--ext/openssl/ossl_pkcs7.c2
-rw-r--r--ext/openssl/ossl_ts.c41
11 files changed, 113 insertions, 64 deletions
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index 6295264a3d..72d697c8ea 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -27,7 +27,7 @@ static VALUE eDateError;
static VALUE half_days_in_day, day_in_nanoseconds;
static double positive_inf, negative_inf;
-// used by deconstruct_keys
+/* used by deconstruct_keys */
static VALUE sym_year, sym_month, sym_day, sym_yday, sym_wday;
static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone;
@@ -4528,6 +4528,7 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
rb_scan_args(argc, argv, "11", &vstr, &vfmt);
StringValue(vstr);
+ if (argc > 1) StringValue(vfmt);
if (!rb_enc_str_asciicompat_p(vstr))
rb_raise(rb_eArgError,
"string should have ASCII compatible encoding");
@@ -4538,7 +4539,6 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
flen = strlen(default_fmt);
}
else {
- StringValue(vfmt);
if (!rb_enc_str_asciicompat_p(vfmt))
rb_raise(rb_eArgError,
"format should have ASCII compatible encoding");
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
index f1c8201de8..1dde5fa3ec 100644
--- a/ext/date/date_strptime.c
+++ b/ext/date/date_strptime.c
@@ -661,6 +661,9 @@ date__strptime(const char *str, size_t slen,
si = date__strptime_internal(str, slen, fmt, flen, hash);
+ if (fail_p())
+ return Qnil;
+
if (slen > si) {
VALUE s;
@@ -668,9 +671,6 @@ date__strptime(const char *str, size_t slen,
set_hash("leftover", s);
}
- if (fail_p())
- return Qnil;
-
cent = del_hash("_cent");
if (!NIL_P(cent)) {
VALUE year;
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 882d47a611..110b5f6b32 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -1367,12 +1367,14 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
MEMCPY(objState, origState, JSON_Generator_State, 1);
- objState->indent = origState->indent;
- objState->space = origState->space;
- objState->space_before = origState->space_before;
- objState->object_nl = origState->object_nl;
- objState->array_nl = origState->array_nl;
- objState->as_json = origState->as_json;
+
+ RB_OBJ_WRITTEN(obj, Qundef, objState->indent);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->space);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->space_before);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl);
+ RB_OBJ_WRITTEN(obj, Qundef, objState->as_json);
+
return obj;
}
@@ -1579,7 +1581,7 @@ static VALUE cState_max_nesting(VALUE self)
static long long_config(VALUE num)
{
- return RTEST(num) ? FIX2LONG(num) : 0;
+ return RTEST(num) ? NUM2LONG(num) : 0;
}
// depth must never be negative; reject early with a clear error.
@@ -1590,6 +1592,9 @@ static long depth_config(VALUE num)
if (RB_UNLIKELY(d < 0)) {
rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
}
+ if (RB_UNLIKELY(d > INT_MAX)) {
+ rb_raise(rb_eArgError, "depth is too large (got %ld)", d);
+ }
return d;
}
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index ebb55656d7..a69590ff9c 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module JSON
- VERSION = '2.19.5'
+ VERSION = '2.19.7'
end
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index a740bd42ed..503bed1fd4 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -385,6 +385,13 @@ static inline char peek(JSON_ParserState *state)
static void cursor_position(JSON_ParserState *state, long *line_out, long *column_out)
{
+ JSON_ASSERT(state->cursor <= state->end);
+
+ // Redundant but helpful for hardening
+ if (RB_UNLIKELY(state->cursor > state->end)) {
+ state->cursor = state->end;
+ }
+
const char *cursor = state->cursor;
long column = 0;
long line = 1;
@@ -1022,6 +1029,13 @@ ALWAYS_INLINE(static) bool string_scan(JSON_ParserState *state)
}
state->cursor++;
}
+
+ // If the string ended with an unterminated escape sequence, we might
+ // have gone past the end.
+ if (RB_UNLIKELY(state->cursor > state->end)) {
+ state->cursor = state->end;
+ }
+
return false;
}
@@ -1202,7 +1216,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
raise_parse_error_at("invalid number: %s", state, start);
}
- exponent = negative_exponent ? -abs_exponent : abs_exponent;
+ if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) {
+ exponent = negative_exponent ? INT64_MIN : INT64_MAX;
+ } else {
+ exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent;
+ }
}
if (integer) {
@@ -1457,18 +1475,21 @@ static void json_ensure_eof(JSON_ParserState *state)
static VALUE convert_encoding(VALUE source)
{
- int encindex = RB_ENCODING_GET(source);
+ StringValue(source);
+ int encindex = RB_ENCODING_GET(source);
- if (RB_LIKELY(encindex == utf8_encindex)) {
- return source;
- }
+ if (RB_LIKELY(encindex == utf8_encindex)) {
+ return source;
+ }
- if (encindex == binary_encindex) {
- // For historical reason, we silently reinterpret binary strings as UTF-8
- return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
- }
+ if (encindex == binary_encindex) {
+ // For historical reason, we silently reinterpret binary strings as UTF-8
+ return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
+ }
- return rb_funcall(source, i_encode, 1, Encoding_UTF_8);
+ source = rb_funcall(source, i_encode, 1, Encoding_UTF_8);
+ StringValue(source);
+ return source;
}
struct parser_config_init_args {
@@ -1583,10 +1604,16 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
return self;
}
-static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
+static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src)
{
- Vsource = convert_encoding(StringValue(Vsource));
- StringValue(Vsource);
+ VALUE Vsource = convert_encoding(src);
+
+ // Ensure the string isn't mutated under us.
+ // The classic API to use is `rb_str_locktmp`, but then we'd
+ // need to use `rb_protect` to make sure we always unlock.
+ if (Vsource == src) {
+ Vsource = rb_str_new_frozen(Vsource);
+ }
VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
rvalue_stack stack = {
@@ -1597,6 +1624,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
long len;
const char *start;
+
RSTRING_GETMEM(Vsource, start, len);
VALUE stack_handle = 0;
@@ -1615,6 +1643,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
// it won't cause a leak.
rvalue_stack_eagerly_release(stack_handle);
RB_GC_GUARD(stack_handle);
+ RB_GC_GUARD(Vsource);
json_ensure_eof(state);
return result;
@@ -1635,9 +1664,6 @@ static VALUE cParserConfig_parse(VALUE self, VALUE Vsource)
static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
{
- Vsource = convert_encoding(StringValue(Vsource));
- StringValue(Vsource);
-
JSON_ParserConfig _config = {0};
JSON_ParserConfig *config = &_config;
parser_config_init(config, opts, false);
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index b644c489b8..68ada01af3 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -573,7 +573,7 @@ dump_object(VALUE obj, struct dump_config *dc)
break;
case T_DATA:
- if (RTYPEDDATA_P(obj)) {
+ {
const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
dump_append(dc, ", \"struct\":\"");
dump_append(dc, type->wrap_struct_name);
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index 46ddfd6021..4e6dea8d03 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -27,17 +27,21 @@ module OpenSSL
end
%w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name|
- klass = Class.new(self) {
- define_method(:initialize, ->(data = nil) {super(name, data)})
- }
-
- singleton = (class << klass; self; end)
-
- singleton.class_eval{
- define_method(:digest) {|data| new.digest(data)}
- define_method(:hexdigest) {|data| new.hexdigest(data)}
- }
+ klass = Class.new(self)
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def initialize(data = nil)
+ super("#{name}", data)
+ end
+ RUBY
+ klass.singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def digest(data)
+ new.digest(data)
+ end
+ def hexdigest(data)
+ new.hexdigest(data)
+ end
+ RUBY
const_set(name.tr('-', '_'), klass)
end
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c
index f70b7f6cf9..99a3589b39 100644
--- a/ext/openssl/ossl_kdf.c
+++ b/ext/openssl/ossl_kdf.c
@@ -39,6 +39,10 @@ pbkdf2_hmac_nogvl(void *args_)
* For more information about PBKDF2, see RFC 2898 Section 5.2
* (https://www.rfc-editor.org/rfc/rfc2898#section-5.2).
*
+ * *NOTE*: This method cannot be interrupted by Timeout.timeout from the
+ * "timeout" library. Do not take parameters from untrusted sources without
+ * enforcing reasonable limits.
+ *
* === Parameters
* pass :: The password.
* salt :: The salt. Salts prevent attacks based on dictionaries of common
@@ -143,6 +147,10 @@ scrypt_nogvl(void *args_)
*
* See RFC 7914 (https://www.rfc-editor.org/rfc/rfc7914) for more information.
*
+ * *NOTE*: This method cannot be interrupted by Timeout.timeout from the
+ * "timeout" library. Do not take parameters from untrusted sources without
+ * enforcing reasonable limits.
+ *
* === Parameters
* pass :: Passphrase.
* salt :: Salt.
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index 32b82a881c..a47c81354c 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -191,6 +191,7 @@ ossl_x509_sk2ary_i(VALUE arg)
static VALUE
ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
{
+ PKCS12 *p12, *p12_orig = DATA_PTR(self);
BIO *in;
VALUE arg, pass, pkey, cert, ca;
char *passphrase;
@@ -198,17 +199,19 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
X509 *x509;
STACK_OF(X509) *x509s = NULL;
int st = 0;
- PKCS12 *pkcs = DATA_PTR(self);
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
in = ossl_obj2bio(&arg);
- d2i_PKCS12_bio(in, &pkcs);
- DATA_PTR(self) = pkcs;
+ p12 = d2i_PKCS12_bio(in, NULL);
BIO_free(in);
+ if (!p12)
+ ossl_raise(ePKCS12Error, "d2i_PKCS12_bio");
+ PKCS12_free(p12_orig);
+ RTYPEDDATA_DATA(self) = p12;
pkey = cert = ca = Qnil;
- if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
+ if (!PKCS12_parse(p12, passphrase, &key, &x509, &x509s))
ossl_raise(ePKCS12Error, "PKCS12_parse");
if (key) {
pkey = rb_protect(ossl_pkey_wrap_i, (VALUE)key, &st);
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 3cf5820c36..44e8cb305b 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -453,7 +453,7 @@ ossl_pkcs7_sym2typeid(VALUE sym)
if(i == numberof(p7_type_tab))
ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
if(strlen(p7_type_tab[i].name) != l) continue;
- if(strcmp(p7_type_tab[i].name, s) == 0){
+ if(memcmp(p7_type_tab[i].name, s, l) == 0){
ret = p7_type_tab[i].nid;
break;
}
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
index 393e08acff..317f7786aa 100644
--- a/ext/openssl/ossl_ts.c
+++ b/ext/openssl/ossl_ts.c
@@ -168,7 +168,7 @@ ossl_ts_req_alloc(VALUE klass)
static VALUE
ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
{
- TS_REQ *ts_req = DATA_PTR(self);
+ TS_REQ *req, *req_orig = DATA_PTR(self);
BIO *in;
VALUE arg;
@@ -178,13 +178,14 @@ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
- ts_req = d2i_TS_REQ_bio(in, &ts_req);
+ req = d2i_TS_REQ_bio(in, NULL);
BIO_free(in);
- if (!ts_req) {
- DATA_PTR(self) = NULL;
- ossl_raise(eTimestampError, "Error when decoding the timestamp request");
+ if (!req) {
+ ossl_raise(eTimestampError,
+ "Error when decoding the timestamp request");
}
- DATA_PTR(self) = ts_req;
+ TS_REQ_free(req_orig);
+ RTYPEDDATA_DATA(self) = req;
return self;
}
@@ -522,18 +523,19 @@ ossl_ts_resp_alloc(VALUE klass)
static VALUE
ossl_ts_resp_initialize(VALUE self, VALUE der)
{
- TS_RESP *ts_resp = DATA_PTR(self);
+ TS_RESP *resp, *resp_orig = DATA_PTR(self);
BIO *in;
der = ossl_to_der_if_possible(der);
- in = ossl_obj2bio(&der);
- ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
+ in = ossl_obj2bio(&der);
+ resp = d2i_TS_RESP_bio(in, NULL);
BIO_free(in);
- if (!ts_resp) {
- DATA_PTR(self) = NULL;
- ossl_raise(eTimestampError, "Error when decoding the timestamp response");
+ if (!resp) {
+ ossl_raise(eTimestampError,
+ "Error when decoding the timestamp response");
}
- DATA_PTR(self) = ts_resp;
+ TS_RESP_free(resp_orig);
+ RTYPEDDATA_DATA(self) = resp;
return self;
}
@@ -876,18 +878,19 @@ ossl_ts_token_info_alloc(VALUE klass)
static VALUE
ossl_ts_token_info_initialize(VALUE self, VALUE der)
{
- TS_TST_INFO *info = DATA_PTR(self);
+ TS_TST_INFO *info, *info_orig = DATA_PTR(self);
BIO *in;
der = ossl_to_der_if_possible(der);
- in = ossl_obj2bio(&der);
- info = d2i_TS_TST_INFO_bio(in, &info);
+ in = ossl_obj2bio(&der);
+ info = d2i_TS_TST_INFO_bio(in, NULL);
BIO_free(in);
if (!info) {
- DATA_PTR(self) = NULL;
- ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
+ ossl_raise(eTimestampError,
+ "Error when decoding the timestamp token info");
}
- DATA_PTR(self) = info;
+ TS_TST_INFO_free(info_orig);
+ RTYPEDDATA_DATA(self) = info;
return self;
}