summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-06-19 04:35:17 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-06-19 04:35:17 +0000
commit9d51cf8a6a5d651c1c4dd363dbf3f4905e3f307d (patch)
tree98247086ea05415f034f0b5a0e6cc97163f47be2
parent6aa71d4c800d11d9735007cf3b063e5ea2fc5941 (diff)
* eval.c (rb_f_require): searches ".rb" and ".so" at the same
time. previous behavior (search ".rb", then ".so") has a security risk (ruby-bugs#PR140). * array.c (rb_ary_to_ary): new function to replace internal rb_Array(), which never calls to_a, but to_ary (rb_Array() might call both). [new] * regex.c (PUSH_FAILURE_POINT): push option status again. * regex.c (re_compile_pattern): avoid pushing unnecessary option_set. * eval.c (rb_load): tainted string is OK if wrapped *and* $SAFE >= 4. * eval.c (rb_thread_start_0): should not nail down higher blocks before preserving original context (i.e. should not alter original context). * eval.c (proc_yield): new method equivalent to Proc#call but no check for number of arguments. [new] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1526 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog33
-rw-r--r--ToDo1
-rw-r--r--array.c17
-rw-r--r--eval.c111
-rw-r--r--file.c100
-rw-r--r--intern.h2
-rw-r--r--io.c6
-rw-r--r--lib/resolv.rb2
-rw-r--r--misc/ruby-mode.el50
-rw-r--r--regex.c31
10 files changed, 249 insertions, 104 deletions
diff --git a/ChangeLog b/ChangeLog
index 748eaf6..548fad8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,42 @@
+Mon Jun 18 17:38:50 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_f_require): searches ".rb" and ".so" at the same
+ time. previous behavior (search ".rb", then ".so") has a
+ security risk (ruby-bugs#PR140).
+
+ * array.c (rb_ary_to_ary): new function to replace internal
+ rb_Array(), which never calls to_a, but to_ary (rb_Array() might
+ call both). [new]
+
+Mon Jun 18 00:43:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (PUSH_FAILURE_POINT): push option status again.
+
+ * regex.c (re_compile_pattern): avoid pushing unnecessary
+ option_set.
+
+Sat Jun 16 10:58:48 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_load): tainted string is OK if wrapped *and*
+ $SAFE >= 4.
+
+Thu Jun 14 16:27:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_start_0): should not nail down higher blocks
+ before preserving original context (i.e. should not alter
+ original context).
+
Wed Jun 13 19:34:59 2001 Akinori MUSHA <knu@iDaemons.org>
* dir.c (Init_Dir): add a new method File::fnmatch? along with
File::Constants::FNM_*. While I am here, FNM_NOCASE is renamed
to FNM_CASEFOLD which is commonly used by *BSD and GNU libc.
+Wed Jun 13 09:33:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_yield): new method equivalent to Proc#call but no
+ check for number of arguments. [new]
+
Tue Jun 12 14:21:28 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* lib/mkmf.rb: target_prefix is only for installation, not for
diff --git a/ToDo b/ToDo
index 7a22319..e9d0d74 100644
--- a/ToDo
+++ b/ToDo
@@ -83,6 +83,7 @@ Standard Libraries
* hash etc. should handle self referenceing array/hash
* move NameError under StandardError.
* library to load per-user profile seeking .ruby_profile or ruby.ini file.
+* warning framework
Extension Libraries
diff --git a/array.c b/array.c
index 010afd9..d0f6977 100644
--- a/array.c
+++ b/array.c
@@ -17,6 +17,7 @@
#include "st.h"
VALUE rb_cArray;
+static ID cmp;
#define ARY_DEFAULT_SIZE 16
@@ -729,6 +730,20 @@ to_ary(ary)
return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
}
+VALUE
+rb_ary_to_ary(obj)
+ VALUE obj;
+{
+ if (NIL_P(obj)) return rb_ary_new2(0);
+ if (TYPE(obj) == T_ARRAY) {
+ return obj;
+ }
+ if (rb_respond_to(obj, rb_intern("to_ary"))) {
+ return rb_convert_type(obj, T_ARRAY, "Array", "to_ary");
+ }
+ return rb_ary_new3(1, obj);
+}
+
extern VALUE rb_output_fs;
static VALUE
@@ -958,8 +973,6 @@ rb_ary_reverse_m(ary)
return rb_ary_reverse(rb_obj_dup(ary));
}
-static ID cmp;
-
static int
sort_1(a, b)
VALUE *a, *b;
diff --git a/eval.c b/eval.c
index 80905ba..314744b 100644
--- a/eval.c
+++ b/eval.c
@@ -1676,7 +1676,7 @@ copy_node_scope(node, rval)
char *file = ruby_sourcefile;\
int line = ruby_sourceline;\
if (TYPE(args) != T_ARRAY)\
- args = rb_Array(args);\
+ args = rb_ary_to_ary(args);\
argc = RARRAY(args)->len;\
argv = ALLOCA_N(VALUE, argc);\
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
@@ -2129,7 +2129,7 @@ rb_eval(self, n)
VALUE v = rb_eval(self, tag->nd_head->nd_head);
int i;
- if (TYPE(v) != T_ARRAY) v = rb_Array(v);
+ if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
for (i=0; i<RARRAY(v)->len; i++) {
if (RTEST(RARRAY(v)->ptr[i])) {
node = node->nd_body;
@@ -2174,7 +2174,7 @@ rb_eval(self, n)
VALUE v = rb_eval(self, tag->nd_head->nd_head);
int i;
- if (TYPE(v) != T_ARRAY) v = rb_Array(v);
+ if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
for (i=0; i<RARRAY(v)->len; i++) {
if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
node = node->nd_body;
@@ -2347,14 +2347,14 @@ rb_eval(self, n)
case NODE_RESTARY:
result = rb_eval(self, node->nd_head);
if (TYPE(result) != T_ARRAY) {
- result = rb_Array(result);
+ result = rb_ary_to_ary(result);
}
break;
case NODE_REXPAND:
result = rb_eval(self, node->nd_head);
if (TYPE(result) != T_ARRAY) {
- result = rb_Array(result);
+ result = rb_ary_to_ary(result);
}
if (RARRAY(result)->len == 0) {
result = Qnil;
@@ -2520,7 +2520,7 @@ rb_eval(self, n)
case NODE_ARGSCAT:
result = rb_ary_concat(rb_eval(self, node->nd_head),
- rb_Array(rb_eval(self, node->nd_body)));
+ rb_ary_to_ary(rb_eval(self, node->nd_body)));
break;
case NODE_ARGSPUSH:
@@ -3546,16 +3546,20 @@ rb_f_block_given_p()
return Qfalse;
}
+#define PC_NONE 0x0
+#define PC_ACHECK 0x1
+#define PC_PCALL 0x2
+
static VALUE
-rb_yield_0(val, self, klass, acheck)
+rb_yield_0(val, self, klass, pcall)
VALUE val, self, klass; /* OK */
- int acheck;
+ int pcall;
{
NODE *node;
volatile VALUE result = Qnil;
volatile VALUE old_cref;
- struct BLOCK *block;
- struct SCOPE *old_scope;
+ struct BLOCK * volatile block;
+ struct SCOPE * volatile old_scope;
struct FRAME frame;
int state;
static unsigned serial = 1;
@@ -3591,7 +3595,7 @@ rb_yield_0(val, self, klass, acheck)
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
if (block->var == (NODE*)1) {
- if (acheck && val != Qundef &&
+ if ((pcall&PC_ACHECK) && val != Qundef &&
TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)",
RARRAY(val)->len);
@@ -3605,14 +3609,14 @@ rb_yield_0(val, self, klass, acheck)
}
else {
if (nd_type(block->var) == NODE_MASGN)
- massign(self, block->var, val, acheck);
+ massign(self, block->var, val, (pcall&PC_ACHECK));
else {
/* argument adjust for proc_call etc. */
- if (acheck && val != Qundef &&
+ if (pcall && val != Qundef &&
TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) {
val = RARRAY(val)->ptr[0];
}
- assign(self, block->var, val, acheck);
+ assign(self, block->var, val, (pcall&PC_ACHECK));
}
}
}
@@ -3621,7 +3625,7 @@ rb_yield_0(val, self, klass, acheck)
}
else {
/* argument adjust for proc_call etc. */
- if (acheck && val != Qundef &&
+ if (pcall && val != Qundef &&
TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) {
val = RARRAY(val)->ptr[0];
}
@@ -5171,7 +5175,12 @@ rb_load(fname, wrap)
NODE *saved_cref = ruby_cref;
TMP_PROTECT;
- SafeStringValue(fname);
+ if (wrap && ruby_safe_level >= 4) {
+ StringValue(fname);
+ }
+ else {
+ SafeStringValue(fname);
+ }
file = rb_find_file(RSTRING(fname)->ptr);
if (!file) {
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
@@ -5402,28 +5411,20 @@ rb_f_require(obj, fname)
}
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
strcpy(buf, RSTRING(fname)->ptr);
- strcat(buf, ".rb");
- if (rb_find_file(buf)) {
+ switch (rb_find_file_noext(buf)) {
+ case 0:
+ break;
+
+ case 1:
fname = rb_str_new2(buf);
- feature = buf;
+ file = feature = buf;
goto load_rb;
- }
- strcpy(buf, RSTRING(fname)->ptr);
- strcat(buf, DLEXT);
- file = rb_find_file(buf);
- if (file) {
- feature = buf;
- goto load_dyna;
- }
-#ifdef DLEXT2
- strcpy(buf, RSTRING(fname)->ptr);
- strcat(buf, DLEXT2);
- file = rb_find_file(buf);
- if (file) {
+
+ default:
feature = buf;
+ file = rb_find_file(buf);
goto load_dyna;
}
-#endif
rb_raise(rb_eLoadError, "No such file to load -- %s",
RSTRING(fname)->ptr);
@@ -6330,8 +6331,9 @@ callargs(args)
}
static VALUE
-proc_call(proc, args)
+proc_invoke(proc, args, pcall)
VALUE proc, args; /* OK */
+ int pcall;
{
struct BLOCK * volatile old_block;
struct BLOCK _block;
@@ -6341,6 +6343,13 @@ proc_call(proc, args)
volatile int orphan;
volatile int safe = ruby_safe_level;
+ if (pcall) {
+ pcall = PC_ACHECK|PC_PCALL;
+ }
+ else {
+ pcall = PC_PCALL;
+ }
+
if (rb_block_given_p() && ruby_frame->last_func) {
rb_warning("block for %s#%s is useless",
rb_class2name(CLASS_OF(proc)),
@@ -6367,7 +6376,7 @@ proc_call(proc, args)
state = EXEC_TAG();
if (state == 0) {
proc_set_safe_level(proc);
- result = rb_yield_0(args, 0, 0, Qtrue);
+ result = rb_yield_0(args, 0, 0, pcall);
}
POP_TAG();
@@ -6399,6 +6408,20 @@ proc_call(proc, args)
}
static VALUE
+proc_call(proc, args)
+ VALUE proc, args; /* OK */
+{
+ return proc_invoke(proc, args, Qtrue);
+}
+
+static VALUE
+proc_yield(proc, args)
+ VALUE proc, args; /* OK */
+{
+ return proc_invoke(proc, args, Qfalse);
+}
+
+static VALUE
proc_arity(proc)
VALUE proc;
{
@@ -6899,6 +6922,7 @@ Init_Proc()
rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1);
rb_define_method(rb_cProc, "call", proc_call, -2);
+ rb_define_method(rb_cProc, "yield", proc_yield, -2);
rb_define_method(rb_cProc, "arity", proc_arity, 0);
rb_define_method(rb_cProc, "[]", proc_call, -2);
rb_define_method(rb_cProc, "==", proc_eq, 1);
@@ -8210,7 +8234,11 @@ rb_thread_start_0(fn, arg, th_arg)
}
#endif
- if (ruby_block) { /* should nail down higher scopes */
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return thread;
+ }
+
+ if (ruby_block) { /* should nail down higher blocks */
struct BLOCK dummy;
dummy.prev = ruby_block;
@@ -8219,9 +8247,6 @@ rb_thread_start_0(fn, arg, th_arg)
}
scope_dup(ruby_scope);
FL_SET(ruby_scope, SCOPE_SHARED);
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return thread;
- }
if (!th->next) {
/* merge in thread list */
@@ -8243,17 +8268,21 @@ rb_thread_start_0(fn, arg, th_arg)
POP_TAG();
status = th->status;
+ if (th == main_thread) ruby_stop(state);
+ rb_thread_remove(th);
+
while (saved_block) {
struct BLOCK *tmp = saved_block;
+ if (curr_thread == main_thread) {
+ printf("free(%p)\n", saved_block);
+ }
if (tmp->frame.argc > 0)
free(tmp->frame.argv);
saved_block = tmp->prev;
free(tmp);
}
- if (th == main_thread) ruby_stop(state);
- rb_thread_remove(th);
if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
th->flags |= THREAD_RAISED;
if (state == TAG_FATAL) {
diff --git a/file.c b/file.c
index 1cff477..66f82bc 100644
--- a/file.c
+++ b/file.c
@@ -2202,48 +2202,99 @@ is_macos_native_path(path)
}
#endif
+static char*
+file_load_ok(file)
+ char *file;
+{
+ FILE *f;
+
+ f = fopen(file, "r");
+ if (f == NULL) return 0;
+ fclose(f);
+ return file;
+}
+
+extern VALUE rb_load_path;
+
+int
+rb_find_file_noext(file)
+ char *file;
+{
+ char *path, *e, *found;
+ char *fend = file + strlen(file);
+ VALUE fname;
+ int i, j;
+
+ static char *ext[] = {
+ ".rb", DLEXT,
+#ifdef DLEXT2
+ DLEXT2,
+#endif
+ 0
+ };
+
+ if (file[0] == '~') {
+ fname = rb_str_new2(file);
+ fname = rb_file_s_expand_path(1, &fname);
+ file = StringValuePtr(fname);
+ }
+
+ if (is_absolute_path(file)) {
+ for (i=0; ext[i]; i++) {
+ strcpy(fend, ext[i]);
+ if (file_load_ok(file)) return i+1;
+ }
+ return 0;
+ }
+
+ if (!rb_load_path) return 0;
+
+ Check_Type(rb_load_path, T_ARRAY);
+ for (i=0;i<RARRAY(rb_load_path)->len;i++) {
+ VALUE str = RARRAY(rb_load_path)->ptr[i];
+
+ SafeStringValue(str);
+ path = RSTRING(str)->ptr;
+ for (j=0; ext[j]; j++) {
+ strcpy(fend, ext[j]);
+ found = dln_find_file(file, path);
+ if (found && file_load_ok(found)) return j+1;
+ }
+ }
+ return 0;
+}
+
char*
rb_find_file(file)
char *file;
{
- extern VALUE rb_load_path;
VALUE vpath, fname;
char *path;
struct stat st;
+ if (file[0] == '~') {
+ fname = rb_str_new2(file);
+ fname = rb_file_s_expand_path(1, &fname);
+ if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) {
+ rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
+ }
+ file = StringValuePtr(fname);
+ }
+
#if defined(__MACOS__) || defined(riscos)
if (is_macos_native_path(file)) {
- FILE *f;
-
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
}
- f= fopen(file, "r");
- if (f == NULL) return 0;
- fclose(f);
- return file;
+ return file_load_ok(file);
}
#endif
if (is_absolute_path(file)) {
- FILE *f;
-
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
}
- f = fopen(file, "r");
- if (f == NULL) return 0;
- fclose(f);
- return file;
- }
-
- if (file[0] == '~') {
- fname = rb_str_new2(file);
- fname = rb_file_s_expand_path(1, &fname);
- if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) {
- rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
- }
- file = StringValuePtr(fname);
+ return file_load_ok(file);
}
if (rb_load_path) {
@@ -2269,10 +2320,7 @@ rb_find_file(file)
}
path = dln_find_file(file, path);
- if (path && stat(path, &st) == 0) {
- return path;
- }
- return 0;
+ return file_load_ok(path);
}
static void
diff --git a/intern.h b/intern.h
index 866df58..ebfc57c 100644
--- a/intern.h
+++ b/intern.h
@@ -27,6 +27,7 @@ VALUE rb_ary_new4 _((long, VALUE *));
VALUE rb_ary_freeze _((VALUE));
VALUE rb_ary_aref _((int, VALUE*, VALUE));
void rb_ary_store _((VALUE, long, VALUE));
+VALUE rb_ary_to_ary _((VALUE));
VALUE rb_ary_to_s _((VALUE));
VALUE rb_ary_push _((VALUE, VALUE));
VALUE rb_ary_pop _((VALUE));
@@ -179,6 +180,7 @@ void rb_thread_atfork _((void));
int eaccess _((const char*, int));
VALUE rb_file_s_expand_path _((int, VALUE *));
void rb_file_const _((const char*, VALUE));
+int rb_find_file_noext _((char*));
char *rb_find_file _((char*));
/* gc.c */
void rb_gc_mark_locations _((VALUE*, VALUE*));
diff --git a/io.c b/io.c
index 3bcf663..ae021f8 100644
--- a/io.c
+++ b/io.c
@@ -3462,10 +3462,8 @@ opt_i_set(val)
VALUE val;
{
if (ruby_inplace_mode) free(ruby_inplace_mode);
- if (!RTEST(val)) {
- ruby_inplace_mode = 0;
- return;
- }
+ ruby_inplace_mode = 0;
+ if (!RTEST(val)) return;
StringValue(val);
ruby_inplace_mode = strdup(RSTRING(val)->ptr);
}
diff --git a/lib/resolv.rb b/lib/resolv.rb
index 782501b..16cf4b5 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -854,7 +854,7 @@ class Resolv
raise DecodeError.new("limit exceed") if @limit < @index + len
arr = @data.unpack("@#{@index}#{template}")
@index += len
- return *arr
+ return arr
end
def get_string
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index 102de81..da31f98 100644
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -660,21 +660,24 @@ An end of a defun is found by moving forward from the beginning of one."
(cond
((featurep 'font-lock)
-
- (setq ruby-font-lock-syntactic-keywords
- '(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
- ("\\(#\\)[{$@]" 1 (1 . nil))
- ("\\(/\\)\\([^/\n]\\|\\/\\)*\\(/\\)"
- (1 (7 . ?'))
- (3 (7 . ?')))
- ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
- ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
- (put major-mode 'font-lock-defaults
- '((ruby-font-lock-keywords)
- nil nil nil
- beginning-of-line
- (font-lock-syntactic-keywords
- . ruby-font-lock-syntactic-keywords)))
+ (or (boundp 'font-lock-variable-name-face)
+ (setq font-lock-variable-name-face font-lock-type-face))
+
+
+ (add-hook 'ruby-mode-hook
+ '(lambda ()
+ (make-local-variable 'font-lock-syntactic-keywords)
+ (setq font-lock-syntactic-keywords
+ '(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
+ ("\\(#\\)[{$@]" 1 (1 . nil))
+ ("\\(/\\)\\([^/\n]\\|\\/\\)*\\(/\\)"
+ (1 (7 . ?'))
+ (3 (7 . ?')))
+ ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
+ ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
+ (setq font-lock-keywords ruby-font-lock-keywords)))
(defun ruby-font-lock-docs (limit)
(if (re-search-forward "^=begin\\(\\s \\|$\\)" limit t)
@@ -687,6 +690,21 @@ An end of a defun is found by moving forward from the beginning of one."
(set-match-data (list beg (point)))
t)))))
+ (defun ruby-font-lock-maybe-docs (limit)
+ (let (beg)
+ (save-excursion
+ (if (and (re-search-backward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t)
+ (string= (match-string-no-properties 1) "begin"))
+ (progn
+ (beginning-of-line)
+ (setq beg (point)))))
+ (if (and beg (and (re-search-forward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t)
+ (string= (match-string-no-properties 1) "end")))
+ (progn
+ (set-match-data (list beg (point)))
+ t)
+ nil)))
+
(defvar ruby-font-lock-keywords
(list
(cons (concat
@@ -741,6 +759,8 @@ An end of a defun is found by moving forward from the beginning of one."
;; embedded document
'(ruby-font-lock-docs
0 font-lock-comment-face t)
+ '(ruby-font-lock-maybe-docs
+ 0 font-lock-comment-face t)
;; constants
'("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
2 font-lock-type-face)
diff --git a/regex.c b/regex.c
index 39e65da..e40c0e4 100644
--- a/regex.c
+++ b/regex.c
@@ -1874,8 +1874,10 @@ re_compile_pattern(pattern, size, bufp)
if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) {
BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on);
}
- BUFPUSH(option_set);
- BUFPUSH(stackp[-1]);
+ if ((options ^ stackp[-1]) != RE_OPTION_IGNORECASE) {
+ BUFPUSH(option_set);
+ BUFPUSH(stackp[-1]);
+ }
}
p0 = b;
options = *--stackp;
@@ -3262,7 +3264,8 @@ re_search(bufp, string, size, startpos, range, regs)
}
if (startpos > size) return -1;
- if (anchor && size > 0 && startpos == size) return -1;
+ if ((anchor || !bufp->can_be_null) && size > 0 && startpos == size)
+ return -1;
val = re_match(bufp, string, size, startpos, regs);
if (val >= 0) return startpos;
if (val == -2) return -2;
@@ -3362,7 +3365,7 @@ re_search(bufp, string, size, startpos, range, regs)
#define NUM_COUNT_ITEMS 2
/* Individual items aside from the registers. */
-#define NUM_NONREG_ITEMS 3
+#define NUM_NONREG_ITEMS 4
/* We push at most this many things on the stack whenever we
fail. The `+ 2' refers to PATTERN_PLACE and STRING_PLACE, which are
@@ -3412,6 +3415,7 @@ re_search(bufp, string, size, startpos, range, regs)
\
*stackp++ = pattern_place; \
*stackp++ = string_place; \
+ *stackp++ = (unsigned char*)options; /* current option status */ \
*stackp++ = (unsigned char*)0; /* non-greedy flag */ \
} while(0)
@@ -3735,15 +3739,11 @@ re_match(bufp, string_arg, size, pos, regs)
int regno = *p++; /* Get which register to match against */
register unsigned char *d2, *dend2;
-#if 0
/* Check if corresponding group is still open */
if (IS_ACTIVE(reg_info[regno])) goto fail;
/* Where in input to try to start matching. */
d2 = regstart[regno];
-#else
- d2 = IS_ACTIVE(reg_info[regno])?old_regstart[regno]:regstart[regno];
-#endif
if (REG_UNSET(d2)) goto fail;
/* Where to stop matching; if both the place to start and
@@ -3791,7 +3791,7 @@ re_match(bufp, string_arg, size, pos, regs)
case stop_nowidth:
EXTRACT_NUMBER_AND_INCR(mcnt, p);
stackp = stackb + mcnt;
- d = stackp[-2];
+ d = stackp[-3];
POP_FAILURE_POINT();
continue;
@@ -4015,8 +4015,8 @@ re_match(bufp, string_arg, size, pos, regs)
because didn't fail. Also remove the register information
put on by the on_failure_jump. */
case finalize_jump:
- if (stackp > stackb && stackp[-2] == d) {
- p = stackp[-3];
+ if (stackp > stackb && stackp[-3] == d) {
+ p = stackp[-4];
POP_FAILURE_POINT();
continue;
}
@@ -4032,7 +4032,7 @@ re_match(bufp, string_arg, size, pos, regs)
case jump:
nofinalize:
EXTRACT_NUMBER_AND_INCR(mcnt, p);
- if (mcnt < 0 && stackp > stackb && stackp[-2] == d) /* avoid infinite loop */
+ if (mcnt < 0 && stackp > stackb && stackp[-3] == d) /* avoid infinite loop */
goto fail;
p += mcnt;
continue;
@@ -4123,7 +4123,7 @@ re_match(bufp, string_arg, size, pos, regs)
case finalize_push:
POP_FAILURE_POINT();
EXTRACT_NUMBER_AND_INCR(mcnt, p);
- if (mcnt < 0 && stackp > stackb && stackp[-2] == d) /* avoid infinite loop */
+ if (mcnt < 0 && stackp > stackb && stackp[-3] == d) /* avoid infinite loop */
goto fail;
PUSH_FAILURE_POINT(p + mcnt, d);
stackp[-1] = NON_GREEDY;
@@ -4288,11 +4288,12 @@ re_match(bufp, string_arg, size, pos, regs)
/* If this failure point is from a dummy_failure_point, just
skip it. */
- if (stackp[-3] == 0 || (best_regs_set && stackp[-1] == NON_GREEDY)) {
+ if (stackp[-4] == 0 || (best_regs_set && stackp[-1] == NON_GREEDY)) {
POP_FAILURE_POINT();
goto fail;
}
- stackp--; /* discard flag */
+ stackp--; /* discard greedy flag */
+ options = (int)*--stackp;
d = *--stackp;
p = *--stackp;
/* Restore register info. */