summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-11-22 07:21:34 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-11-22 07:21:34 +0000
commitd5e7bf424e08f21a6dbc6291e50590a969c6f6db (patch)
treee80041f9f8966c28b12fd3dc221ca467e74a6cdd /util.c
parentb8f2ee898450661a6568f0fd27a9f2266b55239a (diff)
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@ruby-lang.org> 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> 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: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@29855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'util.c')
-rw-r--r--util.c108
1 files changed, 56 insertions, 52 deletions
diff --git a/util.c b/util.c
index 961aaba4c7..62f33683ab 100644
--- a/util.c
+++ b/util.c
@@ -155,79 +155,83 @@ static int valid_filename(char *s);
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
-
- 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++; }
+ rb_str_resize(str, slen);
+ name = StringValueCStr(str);
+ ext = ruby_find_extname(name, &len);
if (*suffix == '.') { /* Style 1 */
- if (strEQ(ext, suffix)) goto fallback;
- strcpy(p, suffix);
- }
- else if (suffix[1] == '\0') { /* Style 2 */
- if (extlen < 4) {
- ext[extlen] = *suffix;
- ext[++extlen] = '\0';
- }
- else if (baselen < 8) {
- *p++ = *suffix;
+ if (ext) {
+ if (strEQ(ext, suffix)) goto fallback;
+ slen = ext - name;
}
- else if (ext[3] != *suffix) {
- ext[3] = *suffix;
+ rb_str_resize(str, slen);
+ 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) {
- buf[7] = *suffix;
+ else { /* Style 3: Panic */
+ 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));
- memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len);
+ memcpy(RSTRING_PTR(str), buf, RSTRING_LEN(str));
}
#if defined(__CYGWIN32__) || defined(_WIN32)