[前][次][番号順一覧][スレッド一覧]

ruby-changes:17843

From: shyouhei <ko1@a...>
Date: Mon, 22 Nov 2010 16:24:11 +0900 (JST)
Subject: [ruby-changes:17843] Ruby:r29855 (ruby_1_8_7): Fri, 2 Jul 2010 14:35:10 +0000 usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>

shyouhei	2010-11-22 16:21:34 +0900 (Mon, 22 Nov 2010)

  New Revision: 29855

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29855

  Log:
    Fri, 2 Jul 2010 14:35:10 +0000  usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
     merge revision(s) 28525:28568:
     
     	* file.c (ruby_find_basename, ruby_find_extname): split from
     	  rb_file_s_basename() and rb_file_s_extname().
    
    * util.c (ruby_add_suffix): support arbitrary length of the suffix
      to get rid of the potential buffer overflow.
      reported by tarui.
    
    git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@28526 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
    Signed-off-by: URABE, Shyouhei <shyouhei@r...>
    
    merge from trunk (r28565)
    
    * file.c (ruby_find_basename): set correct baselen.
    
    git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@28566 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
    Signed-off-by: URABE, Shyouhei <shyouhei@r...>
    
    merge from trunk (r28565)
    
    * file.c (ruby_find_basename): set correct baselen.
    
    git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@28568 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
    Signed-off-by: URABE, Shyouhei <shyouhei@r...>

  Modified files:
    branches/ruby_1_8_7/ChangeLog
    branches/ruby_1_8_7/file.c
    branches/ruby_1_8_7/util.c
    branches/ruby_1_8_7/version.h

Index: ruby_1_8_7/util.c
===================================================================
--- ruby_1_8_7/util.c	(revision 29854)
+++ ruby_1_8_7/util.c	(revision 29855)
@@ -155,79 +155,83 @@
 static const char suffix1[] = ".$$$";
 static const char suffix2[] = ".~~~";
 
-#define ext (&buf[1000])
-
 #define strEQ(s1,s2) (strcmp(s1,s2) == 0)
 
+extern const char *ruby_find_basename(const char *, long *, long *);
+extern const char *ruby_find_extname(const char *, long *);
+
 void
-ruby_add_suffix(str, suffix)
-    VALUE str;
-    char *suffix;
+ruby_add_suffix(VALUE str, const char *suffix)
 {
     int baselen;
     int extlen = strlen(suffix);
-    char *s, *t, *p;
+    char *p, *q;
     long slen;
     char buf[1024];
+    const char *name;
+    const char *ext;
+    long len;
 
-    if (RSTRING(str)->len > 1000)
-        rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
-		 RSTRING(str)->len);
+    name = StringValueCStr(str);
+    slen = strlen(name);
+    if (slen > sizeof(buf) - 1)
+	rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
+		 slen);
 
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32)
     /* Style 0 */
-    slen = RSTRING(str)->len;
     rb_str_cat(str, suffix, extlen);
-#if defined(DJGPP)
-    if (_USE_LFN) return;
-#else
-    if (valid_filename(RSTRING(str)->ptr)) return;
-#endif
+    if (valid_filename(RSTRING_PTR(str))) return;
 
     /* Fooey, style 0 failed.  Fix str before continuing. */
-    RSTRING(str)->ptr[RSTRING(str)->len = slen] = '\0';
-#endif
+    rb_str_resize(str, slen);
+    name = StringValueCStr(str);
+    ext = ruby_find_extname(name, &len);
 
-    slen = extlen;
-    t = buf; baselen = 0; s = RSTRING(str)->ptr;
-    while ((*t = *s) && *s != '.') {
-	baselen++;
-	if (*s == '\\' || *s == '/') baselen = 0;
- 	s++; t++;
-    }
-    p = t;
-
-    t = ext; extlen = 0;
-    while (*t++ = *s++) extlen++;
-    if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }
-
     if (*suffix == '.') {        /* Style 1 */
-        if (strEQ(ext, suffix)) goto fallback;
-	strcpy(p, suffix);
+	if (ext) {
+	    if (strEQ(ext, suffix)) goto fallback;
+	    slen = ext - name;
+	}
+	rb_str_resize(str, slen);
+	rb_str_cat(str, suffix, extlen);
     }
-    else if (suffix[1] == '\0') {  /* Style 2 */
-        if (extlen < 4) { 
-	    ext[extlen] = *suffix;
-	    ext[++extlen] = '\0';
-        }
-	else if (baselen < 8) {
-   	    *p++ = *suffix;
+    else {
+	strncpy(buf, name, slen);
+	if (ext)
+	    p = buf + (ext - name);
+	else
+	    p = buf + slen;
+	p[len] = '\0';
+	if (suffix[1] == '\0') {  /* Style 2 */
+	    if (len <= 3) {
+		p[len] = *suffix;
+		p[++len] = '\0';
+	    }
+	    else if ((q = (char *)ruby_find_basename(buf, &baselen, 0)) &&
+		     baselen < 8) {
+		q += baselen;
+		*q++ = *suffix;
+		if (ext) {
+		    strncpy(q, ext, ext - name);
+		    q[ext - name + 1] = '\0';
+		}
+		else
+		    *q = '\0';
+	    }
+	    else if (len == 4 && p[3] != *suffix)
+		p[3] = *suffix;
+	    else if (baselen == 8 && q[7] != *suffix)
+		q[7] = *suffix;
+	    else
+		goto fallback;
 	}
-	else if (ext[3] != *suffix) {
-	    ext[3] = *suffix;
+	else { /* Style 3:  Panic */
+	  fallback:
+	    (void)memcpy(p, !ext || strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
 	}
-	else if (buf[7] != *suffix) {
-	    buf[7] = *suffix;
-	}
-	else goto fallback;
-	strcpy(p, ext);
     }
-    else { /* Style 3:  Panic */
-fallback:
-	(void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
-    }
     rb_str_resize(str, strlen(buf));
-    memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len);
+    memcpy(RSTRING_PTR(str), buf, RSTRING_LEN(str));
 }
 
 #if defined(__CYGWIN32__) || defined(_WIN32)
Index: ruby_1_8_7/ChangeLog
===================================================================
--- ruby_1_8_7/ChangeLog	(revision 29854)
+++ ruby_1_8_7/ChangeLog	(revision 29855)
@@ -1,3 +1,16 @@
+Wed Jul  7 13:24:24 2010  NAKAMURA Usaku  <usa@r...>
+
+	* file.c (ruby_find_basename): set correct baselen.
+
+Fri Jul  2 23:34:45 2010  NAKAMURA Usaku  <usa@r...>
+
+	* file.c (ruby_find_basename, ruby_find_extname): split from
+	  rb_file_s_basename() and rb_file_s_extname().
+
+	* util.c (ruby_add_suffix): support arbitrary length of the suffix
+	  to get rid of the potential buffer overflow.
+	  reported by tarui.
+
 Sat Jul 10 10:51:29 2010  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* configure.in: fix use_context condition inversion.
Index: ruby_1_8_7/version.h
===================================================================
--- ruby_1_8_7/version.h	(revision 29854)
+++ ruby_1_8_7/version.h	(revision 29855)
@@ -2,7 +2,7 @@
 #define RUBY_RELEASE_DATE "2010-11-22"
 #define RUBY_VERSION_CODE 187
 #define RUBY_RELEASE_CODE 20101122
-#define RUBY_PATCHLEVEL 304
+#define RUBY_PATCHLEVEL 305
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
Index: ruby_1_8_7/file.c
===================================================================
--- ruby_1_8_7/file.c	(revision 29854)
+++ ruby_1_8_7/file.c	(revision 29855)
@@ -2881,24 +2881,17 @@
  *     File.basename("/home/gumby/work/ruby.rb", ".rb")   #=> "ruby"
  */
 
-static VALUE
-rb_file_s_basename(argc, argv)
-    int argc;
-    VALUE *argv;
+const char *
+ruby_find_basename(name, baselen, alllen)
+    const char *name;
+    long *baselen, *alllen;
 {
-    VALUE fname, fext, basename;
-    const char *name, *p;
+    const char *p, *q, *e;
 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
     const char *root;
 #endif
-    int f, n;
+    long f = 0, n = -1;
 
-    if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
-	StringValue(fext);
-    }
-    StringValue(fname);
-    if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr))
-	return fname;
     name = skipprefix(name);
 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
     root = name;
@@ -2937,11 +2930,59 @@
 #else
 	n = chompdirsep(p) - p;
 #endif
+	for (q = p; q - p < n && *q == '.'; q++);
+	for (e = 0; q - p < n; q = CharNext(q)) {
+	    if (*q == '.') e = q;
+	}
+	if (e) f = e - p;
+	else f = n;
+    }
+
+    if (baselen)
+	*baselen = f;
+    if (alllen)
+	*alllen = n;
+    return p;
+}
+
+/*
+ *  call-seq:
+ *     File.basename(file_name [, suffix] ) -> base_name
+ *
+ *  Returns the last component of the filename given in <i>file_name</i>,
+ *  which must be formed using forward slashes (``<code>/</code>'')
+ *  regardless of the separator used on the local file system. If
+ *  <i>suffix</i> is given and present at the end of <i>file_name</i>,
+ *  it is removed.
+ *
+ *     File.basename("/home/gumby/work/ruby.rb")          #=> "ruby.rb"
+ *     File.basename("/home/gumby/work/ruby.rb", ".rb")   #=> "ruby"
+ */
+
+static VALUE
+rb_file_s_basename(argc, argv)
+    int argc;
+    VALUE *argv;
+{
+    VALUE fname, fext, basename;
+    const char *name, *p;
+    long f, n;
+
+    if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
+	StringValue(fext);
+    }
+    StringValue(fname);
+    if (RSTRING_LEN(fname) == 0 || !*(name = RSTRING_PTR(fname)))
+	return fname;
+
+    p = ruby_find_basename(name, &f, &n);
+    if (n >= 0) {
 	if (NIL_P(fext) || !(f = rmext(p, n, StringValueCStr(fext)))) {
 	    f = n;
 	}
 	if (f == RSTRING_LEN(fname)) return fname;
     }
+
     basename = rb_str_new(p, f);
     OBJ_INFECT(basename, fname);
     return basename;
@@ -2999,27 +3040,24 @@
 }
 
 /*
- *  call-seq:
- *     File.extname(path) -> string
- *  
- *  Returns the extension (the portion of file name in <i>path</i>
- *  after the period).
- *     
- *     File.extname("test.rb")         #=> ".rb"
- *     File.extname("a/b/d/test.rb")   #=> ".rb"
- *     File.extname("test")            #=> ""
- *     File.extname(".profile")        #=> ""
- *     
+ * accept a String, and return the pointer of the extension.
+ * if len is passed, set the length of extension to it.
+ * returned pointer is in ``name'' or NULL.
+ *                 returns   *len
+ *   no dot        NULL      0
+ *   dotfile       top       0
+ *   end with dot  dot       1
+ *   .ext          dot       len of .ext
+ *   .ext:stream   dot       len of .ext without :stream (NT only)
+ *
  */
-
-static VALUE
-rb_file_s_extname(klass, fname)
-    VALUE klass, fname;
+const char *
+ruby_find_extname(name, len)
+    const char *name;
+    long *len;
 {
-    const char *name, *p, *e;
-    VALUE extname;
+    const char *p, *e;
 
-    name = StringValueCStr(fname);
     p = strrdirsep(name);	/* get the last path component */
     if (!p)
 	p = name;
@@ -3054,9 +3092,46 @@
 	    break;
 	p = CharNext(p);
     }
-    if (!e || e == name || e+1 == p)	/* no dot, or the only dot is first or end? */
+
+    if (len) {
+	/* no dot, or the only dot is first or end? */
+	if (!e || e == name)
+	    *len = 0;
+	else if (e+1 == p)
+	    *len = 1;
+	else
+	    *len = p - e;
+    }
+    return e;
+}
+
+/*
+ *  call-seq:
+ *     File.extname(path) -> string
+ *
+ *  Returns the extension (the portion of file name in <i>path</i>
+ *  after the period).
+ *
+ *     File.extname("test.rb")         #=> ".rb"
+ *     File.extname("a/b/d/test.rb")   #=> ".rb"
+ *     File.extname("test")            #=> ""
+ *     File.extname(".profile")        #=> ""
+ *
+ */
+
+static VALUE
+rb_file_s_extname(klass, fname)
+    VALUE klass, fname;
+{
+    const char *name, *e;
+    long len;
+    VALUE extname;
+
+    name = StringValueCStr(fname);
+    e = ruby_find_extname(name, &len);
+    if (len <= 1)
 	return rb_str_new(0, 0);
-    extname = rb_str_new(e, p - e);	/* keep the dot, too! */
+    extname = rb_str_new(e, len);	/* keep the dot, too! */
     OBJ_INFECT(extname, fname);
     return extname;
 }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]