* 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>
* 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;
char *p;
const char *f = " ";
long n, llen, rlen;
long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
volatile VALUE pad;
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);
rlen = n - llen;
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);
while (llen) {
if (flen <= 1) {
*p++ = *f;
llen--;
}
else if (llen > fclen) {
if (flen <= 1) {
memset(p, *f, llen);
p += llen;
}
else {
while (llen > fclen) {
memcpy(p,f,flen);
p += flen;
llen -= fclen;
}
else {
char *fp = str_nth(f, f+flen, llen, enc, singlebyte);
n = fp - f;
memcpy(p,f,n);
p+=n;
break;
if (llen > 0) {
memcpy(p, f, llen2);
p += llen2;
}
}
memcpy(p, RSTRING_PTR(str), RSTRING_LEN(str));
p+=RSTRING_LEN(str);
while (rlen) {
if (flen <= 1) {
*p++ = *f;
rlen--;
}
else if (rlen > fclen) {
memcpy(p, RSTRING_PTR(str), size);
p += size;
if (flen <= 1) {
memset(p, *f, rlen);
p += rlen;
}
else {
while (rlen > fclen) {
memcpy(p,f,flen);
p += flen;
rlen -= fclen;
}
else {
char *fp = str_nth(f, f+flen, rlen, enc, singlebyte);
n = fp - f;
memcpy(p,f,n);
p+=n;
break;
if (rlen > 0) {
memcpy(p, f, rlen2);
p += rlen2;
}
}
*p = '\0';