Skip to content

Commit

Permalink
Fri, 2 Jul 2010 14:35:10 +0000 usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe…
Browse files Browse the repository at this point in the history
…69b080e>

 merge revision(s) 28525:28568:
 ?\012
 	* 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@ruby-lang.org>
?\012
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@ruby-lang.org>
?\012
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@ruby-lang.org>



git-svn-id: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_7@29855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
shyouhei committed Nov 22, 2010
1 parent b9b8e97 commit dd92e04
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 86 deletions.
13 changes: 13 additions & 0 deletions ChangeLog
@@ -1,3 +1,16 @@
Wed Jul 7 13:24:24 2010 NAKAMURA Usaku <usa@ruby-lang.org>

* file.c (ruby_find_basename): set correct baselen.

Fri Jul 2 23:34:45 2010 NAKAMURA Usaku <usa@ruby-lang.org>

* 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@gmail.com> Sat Jul 10 10:51:29 2010 KOSAKI Motohiro <kosaki.motohiro@gmail.com>


* configure.in: fix use_context condition inversion. * configure.in: fix use_context condition inversion.
Expand Down
141 changes: 108 additions & 33 deletions file.c
Expand Up @@ -2881,24 +2881,17 @@ rmext(p, l1, e)
* File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby" * File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby"
*/ */


static VALUE const char *
rb_file_s_basename(argc, argv) ruby_find_basename(name, baselen, alllen)
int argc; const char *name;
VALUE *argv; long *baselen, *alllen;
{ {
VALUE fname, fext, basename; const char *p, *q, *e;
const char *name, *p;
#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
const char *root; const char *root;
#endif #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); name = skipprefix(name);
#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
root = name; root = name;
Expand Down Expand Up @@ -2937,11 +2930,59 @@ rb_file_s_basename(argc, argv)
#else #else
n = chompdirsep(p) - p; n = chompdirsep(p) - p;
#endif #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)))) { if (NIL_P(fext) || !(f = rmext(p, n, StringValueCStr(fext)))) {
f = n; f = n;
} }
if (f == RSTRING_LEN(fname)) return fname; if (f == RSTRING_LEN(fname)) return fname;
} }

basename = rb_str_new(p, f); basename = rb_str_new(p, f);
OBJ_INFECT(basename, fname); OBJ_INFECT(basename, fname);
return basename; return basename;
Expand Down Expand Up @@ -2999,27 +3040,24 @@ rb_file_s_dirname(klass, fname)
} }


/* /*
* call-seq: * accept a String, and return the pointer of the extension.
* File.extname(path) -> string * if len is passed, set the length of extension to it.
* * returned pointer is in ``name'' or NULL.
* Returns the extension (the portion of file name in <i>path</i> * returns *len
* after the period). * no dot NULL 0
* * dotfile top 0
* File.extname("test.rb") #=> ".rb" * end with dot dot 1
* File.extname("a/b/d/test.rb") #=> ".rb" * .ext dot len of .ext
* File.extname("test") #=> "" * .ext:stream dot len of .ext without :stream (NT only)
* File.extname(".profile") #=> "" *
*
*/ */

const char *
static VALUE ruby_find_extname(name, len)
rb_file_s_extname(klass, fname) const char *name;
VALUE klass, fname; long *len;
{ {
const char *name, *p, *e; const char *p, *e;
VALUE extname;


name = StringValueCStr(fname);
p = strrdirsep(name); /* get the last path component */ p = strrdirsep(name); /* get the last path component */
if (!p) if (!p)
p = name; p = name;
Expand Down Expand Up @@ -3054,9 +3092,46 @@ rb_file_s_extname(klass, fname)
break; break;
p = CharNext(p); 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); 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); OBJ_INFECT(extname, fname);
return extname; return extname;
} }
Expand Down
108 changes: 56 additions & 52 deletions util.c
Expand Up @@ -155,79 +155,83 @@ static int valid_filename(char *s);
static const char suffix1[] = ".$$$"; static const char suffix1[] = ".$$$";
static const char suffix2[] = ".~~~"; static const char suffix2[] = ".~~~";


#define ext (&buf[1000])

#define strEQ(s1,s2) (strcmp(s1,s2) == 0) #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 void
ruby_add_suffix(str, suffix) ruby_add_suffix(VALUE str, const char *suffix)
VALUE str;
char *suffix;
{ {
int baselen; int baselen;
int extlen = strlen(suffix); int extlen = strlen(suffix);
char *s, *t, *p; char *p, *q;
long slen; long slen;
char buf[1024]; char buf[1024];
const char *name;
const char *ext;
long len;


if (RSTRING(str)->len > 1000) name = StringValueCStr(str);
rb_fatal("Cannot do inplace edit on long filename (%ld characters)", slen = strlen(name);
RSTRING(str)->len); 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 */ /* Style 0 */
slen = RSTRING(str)->len;
rb_str_cat(str, suffix, extlen); rb_str_cat(str, suffix, extlen);
#if defined(DJGPP) if (valid_filename(RSTRING_PTR(str))) return;
if (_USE_LFN) return;
#else
if (valid_filename(RSTRING(str)->ptr)) return;
#endif


/* Fooey, style 0 failed. Fix str before continuing. */ /* Fooey, style 0 failed. Fix str before continuing. */
RSTRING(str)->ptr[RSTRING(str)->len = slen] = '\0'; rb_str_resize(str, slen);
#endif 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 (*suffix == '.') { /* Style 1 */
if (strEQ(ext, suffix)) goto fallback; if (ext) {
strcpy(p, suffix); if (strEQ(ext, suffix)) goto fallback;
} slen = ext - name;
else if (suffix[1] == '\0') { /* Style 2 */
if (extlen < 4) {
ext[extlen] = *suffix;
ext[++extlen] = '\0';
}
else if (baselen < 8) {
*p++ = *suffix;
} }
else if (ext[3] != *suffix) { rb_str_resize(str, slen);
ext[3] = *suffix; rb_str_cat(str, suffix, extlen);
}
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 (buf[7] != *suffix) { else { /* Style 3: Panic */
buf[7] = *suffix; fallback:
(void)memcpy(p, !ext || strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
} }
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)); 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) #if defined(__CYGWIN32__) || defined(_WIN32)
Expand Down
2 changes: 1 addition & 1 deletion version.h
Expand Up @@ -2,7 +2,7 @@
#define RUBY_RELEASE_DATE "2010-11-22" #define RUBY_RELEASE_DATE "2010-11-22"
#define RUBY_VERSION_CODE 187 #define RUBY_VERSION_CODE 187
#define RUBY_RELEASE_CODE 20101122 #define RUBY_RELEASE_CODE 20101122
#define RUBY_PATCHLEVEL 304 #define RUBY_PATCHLEVEL 305


#define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8 #define RUBY_VERSION_MINOR 8
Expand Down

0 comments on commit dd92e04

Please sign in to comment.