summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-12-07 04:11:26 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-12-07 04:11:26 +0000
commit219d8f485cb820a548862f7e6b45ddf0ce27c279 (patch)
tree789bf1a5a3defe230b5a32878d37e523340de4dd
parent287facbf5429094fd49619d5504d0b33a32e3152 (diff)
downloadruby-219d8f485cb820a548862f7e6b45ddf0ce27c279.tar.gz
ruby-219d8f485cb820a548862f7e6b45ddf0ce27c279.tar.xz
ruby-219d8f485cb820a548862f7e6b45ddf0ce27c279.zip
* 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: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_9_1@26038 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--string.c61
2 files changed, 40 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index de812d360..5c01b2a60 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sat Dec 5 18:52:56 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.
+
Sat Dec 5 14:29:49 2009 Yuki Sonoda (Yugui) <yugui@yugui.jp>
* lib/irb/extend-command.rb (IRB::ExtendCommandBundle::def_extend_command):
diff --git a/string.c b/string.c
index 725ba34ee..f5945985c 100644
--- a/string.c
+++ b/string.c
@@ -6473,7 +6473,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;
@@ -6497,44 +6497,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';