aboutsummaryrefslogtreecommitdiffstats
path: root/ext/openssl/ossl_cipher.c
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-07-16 22:56:20 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-07-24 13:15:02 +0900
commitc0548c94e499f38fd4077f6e9ca3e7e6a9c670b2 (patch)
treed1cc99bbf8bee1a75586003538846aa275b52f3d /ext/openssl/ossl_cipher.c
parent4b860f5fc9c8742f90e9609274638628c3253bc8 (diff)
downloadruby-openssl-c0548c94e499f38fd4077f6e9ca3e7e6a9c670b2.tar.gz
cipher: fix handling huge data larger than INT_MAX bytes
The function ossl_cipher_update_long() was added to fix this in r48923 (ossl_cipher.c: workaround of OpenSSL API, 2014-12-23), but it didn't work well. [Bug #10633] This can be tested by running: $ fallocate -l 2G data.img $ ruby -ropenssl <<EOF cipher = OpenSSL::Cipher.new("aes-128-ecb").encrypt cipher.key = "\x00" * 16 ct = cipher.update(File.read("data.img")) << cipher.final p ct.bytesize EOF
Diffstat (limited to 'ext/openssl/ossl_cipher.c')
-rw-r--r--ext/openssl/ossl_cipher.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index a786ffab..89744a18 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -331,25 +331,23 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p
const unsigned char *in, long in_len)
{
int out_part_len;
+ int limit = INT_MAX / 2 + 1;
long out_len = 0;
-#define UPDATE_LENGTH_LIMIT INT_MAX
-
-#if SIZEOF_LONG > UPDATE_LENGTH_LIMIT
- if (in_len > UPDATE_LENGTH_LIMIT) {
- const int in_part_len = (UPDATE_LENGTH_LIMIT / 2 + 1) & ~1;
- do {
- if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
- &out_part_len, in, in_part_len))
- return 0;
- out_len += out_part_len;
- in += in_part_len;
- } while ((in_len -= in_part_len) > UPDATE_LENGTH_LIMIT);
- }
-#endif
- if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
- &out_part_len, in, (int)in_len))
- return 0;
- if (out_len_ptr) *out_len_ptr = out_len += out_part_len;
+
+ do {
+ int in_part_len = in_len > limit ? limit : in_len;
+
+ if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
+ &out_part_len, in, in_part_len))
+ return 0;
+
+ out_len += out_part_len;
+ in += in_part_len;
+ } while ((in_len -= limit) > 0);
+
+ if (out_len_ptr)
+ *out_len_ptr = out_len;
+
return 1;
}