* string.c (rb_str_justify): CVE-2009-4124.

Fixes a bug reported by 
  Emmanouel Kellinis <Emmanouel.Kellinis AT kpmg.co.uk>, KPMG London;
  Patch by nobu.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26038 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
yugui 2009-12-07 04:11:26 +00:00
parent 753de85e40
commit 1c2ef61035
2 changed files with 40 additions and 28 deletions

View File

@ -1,3 +1,10 @@
Mon Dec 7 13:05:59 2009 Yuki Sonoda (Yugui) <yugui@yugui.jp>
* string.c (rb_str_justify): CVE-2009-4124.
Fixes a bug reported by
Emmanouel Kellinis <Emmanouel.Kellinis AT kpmg.co.uk>, KPMG London;
Patch by nobu.
Sun Dec 6 23:50:46 2009 NARUSE, Yui <naruse@ruby-lang.org> Sun Dec 6 23:50:46 2009 NARUSE, Yui <naruse@ruby-lang.org>
* strftime.c: %l should be 1..12 instead of 0..12 [ruby-core:27072] * strftime.c: %l should be 1..12 instead of 0..12 [ruby-core:27072]

View File

@ -6593,7 +6593,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
VALUE res; VALUE res;
char *p; char *p;
const char *f = " "; const char *f = " ";
long n, llen, rlen; long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
volatile VALUE pad; volatile VALUE pad;
int singlebyte = 1, cr; int singlebyte = 1, cr;
@ -6617,44 +6617,49 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2); llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
rlen = n - llen; rlen = n - llen;
cr = ENC_CODERANGE(str); cr = ENC_CODERANGE(str);
res = rb_str_new5(str, 0, RSTRING_LEN(str)+n*flen/fclen+2); if (flen > 1) {
llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte);
rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte);
}
size = RSTRING_LEN(str);
if ((len = llen / fclen + rlen / fclen) >= LONG_MAX / flen ||
(len *= flen) >= LONG_MAX - llen2 - rlen2 ||
(len += llen2 + rlen2) >= LONG_MAX - size) {
rb_raise(rb_eArgError, "argument too big");
}
len += size;
res = rb_str_new5(str, 0, len);
p = RSTRING_PTR(res); p = RSTRING_PTR(res);
while (llen) { if (flen <= 1) {
if (flen <= 1) { memset(p, *f, llen);
*p++ = *f; p += llen;
llen--; }
} else {
else if (llen > fclen) { while (llen > fclen) {
memcpy(p,f,flen); memcpy(p,f,flen);
p += flen; p += flen;
llen -= fclen; llen -= fclen;
} }
else { if (llen > 0) {
char *fp = str_nth(f, f+flen, llen, enc, singlebyte); memcpy(p, f, llen2);
n = fp - f; p += llen2;
memcpy(p,f,n);
p+=n;
break;
} }
} }
memcpy(p, RSTRING_PTR(str), RSTRING_LEN(str)); memcpy(p, RSTRING_PTR(str), size);
p+=RSTRING_LEN(str); p += size;
while (rlen) { if (flen <= 1) {
if (flen <= 1) { memset(p, *f, rlen);
*p++ = *f; p += rlen;
rlen--; }
} else {
else if (rlen > fclen) { while (rlen > fclen) {
memcpy(p,f,flen); memcpy(p,f,flen);
p += flen; p += flen;
rlen -= fclen; rlen -= fclen;
} }
else { if (rlen > 0) {
char *fp = str_nth(f, f+flen, rlen, enc, singlebyte); memcpy(p, f, rlen2);
n = fp - f; p += rlen2;
memcpy(p,f,n);
p+=n;
break;
} }
} }
*p = '\0'; *p = '\0';