summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-29 05:56:04 (GMT)
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-29 05:56:04 (GMT)
commit97e6aaca7c7fe2b3d31d2cd94574710318def24d (patch)
treea23a36e85df875e63e3145f5173842a5b0c5317d /dir.c
parent9c5d90b516e665294fa673ca6d9819d7406a7629 (diff)
dir.c: do not assume NUL terminator
* dir.c (rb_push_glob): do not assume string is NUL terminated always, shared substring may not in the future. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63034 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/dir.c b/dir.c
index 1343225..6d2bedf 100644
--- a/dir.c
+++ b/dir.c
@@ -2534,6 +2534,7 @@ static VALUE
rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */
{
long offset = 0;
+ long len;
VALUE ary;
/* can contain null bytes as separators */
@@ -2546,19 +2547,21 @@ rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */
}
ary = rb_ary_new();
- while (offset < RSTRING_LEN(str)) {
- char *p, *pend;
+ while (offset < (len = RSTRING_LEN(str))) {
int status;
- p = RSTRING_PTR(str) + offset;
- status = push_glob(ary, rb_enc_str_new(p, strlen(p), rb_enc_get(str)),
+ long rest = len - offset;
+ const char *pbeg = RSTRING_PTR(str), *p = pbeg + offset;
+ const char *pend = memchr(p, '\0', rest);
+ if (pend) {
+ rest = ++pend - p;
+ offset = pend - pbeg;
+ }
+ else {
+ offset = len;
+ }
+ status = push_glob(ary, rb_str_subseq(str, p-pbeg, rest),
base, flags);
if (status) GLOB_JUMP_TAG(status);
- if (offset >= RSTRING_LEN(str)) break;
- p += strlen(p) + 1;
- pend = RSTRING_PTR(str) + RSTRING_LEN(str);
- while (p < pend && !*p)
- p++;
- offset = p - RSTRING_PTR(str);
}
return ary;