ruby-changes:53459
From: shyouhei <ko1@a...>
Date: Mon, 12 Nov 2018 10:08:43 +0900 (JST)
Subject: [ruby-changes:53459] shyouhei:r65675 (trunk): ~(unsigned char) is not unsigned char
shyouhei 2018-11-12 10:08:35 +0900 (Mon, 12 Nov 2018) New Revision: 65675 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65675 Log: ~(unsigned char) is not unsigned char The unary ~ operator excercises integer promotion of the operand _before_ actually applying bitwise complement (cf: ISO/IEC 9899:1990 section 6.3.3.3). Which means `~buf[i]` is in fact `(int)~(int)buf[i]`. The problem is, when buf[i] is 0xFF: buf[i] 0xFF (int)buf[i] 0x0000_00FF ~(int)buf[i] 0xFFFF_FF00 This is -256, out of unsigned char range. The proposed fix is to change the char signed. By doing so, buf[i] 0xFF (signed char)buf[i] 0xFF (int)(signed char)buf[i] 0xFFFF_FFFF ~(int)(signed char)buf[i] 0x0000_0000 This is 0, does not overflow. Modified files: trunk/bignum.c Index: bignum.c =================================================================== --- bignum.c (revision 65674) +++ bignum.c (revision 65675) @@ -616,8 +616,12 @@ static int https://github.com/ruby/ruby/blob/trunk/bignum.c#L616 bytes_2comp(unsigned char *buf, size_t len) { size_t i; - for (i = 0; i < len; i++) - buf[i] = ~buf[i]; + for (i = 0; i < len; i++) { + signed char c = buf[i]; + signed int d = ~c; + unsigned int e = d & 0xFF; + buf[i] = e; + } for (i = 0; i < len; i++) { buf[i]++; if (buf[i] != 0) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/