Skip to content

Commit 1bf687b

Browse files
rheniumnobu
andcommitted
Fix Digest::SHA1#update with large input
Digest::SHA1#update fails when a very large String is passed in a single call. Passing 2**29 bytes (512 MB) or more at once does not update the message length counter correctly, which results in producing an incorrect output. $ ruby -rdigest -e'd=Digest::SHA1.new; d<<"a"*(512*1024*1024); puts d.hexdigest' 40cd9c4b14e7b8d0940a3a92c8a7661fad85a821 $ ruby -rdigest -e'd=Digest::SHA1.new; 512.times{d<<"a"*(1024*1024)}; puts d.hexdigest' 0ea59bfe8787939816796610c73deb1c625e03ed $ ruby -e'print "a"*(512*1024*1024)'|sha1sum 0ea59bfe8787939816796610c73deb1c625e03ed - Passing 2**32 bytes or more causes an infinite loop because the loop counter is too small. Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
1 parent 5f17e37 commit 1bf687b

1 file changed

Lines changed: 4 additions & 2 deletions

File tree

ext/digest/sha1/sha1.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,16 @@ int SHA1_Init(SHA1_CTX *context)
220220
*/
221221
void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
222222
{
223-
uint32_t i, j;
223+
size_t i;
224+
uint32_t j;
224225

225226
_DIAGASSERT(context != 0);
226227
_DIAGASSERT(data != 0);
227228

228229
j = context->count[0];
229230
if ((context->count[0] += len << 3) < j)
230-
context->count[1] += (len>>29)+1;
231+
context->count[1]++;
232+
context->count[1] += (uint32_t)(len >> 29);
231233
j = (j >> 3) & 63;
232234
if ((j + len) > 63) {
233235
(void)memcpy(&context->buffer[j], data, (i = 64-j));

0 commit comments

Comments
 (0)