summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorguy Decoux <ts@moulon.inra.fr>2009-02-28 20:04:27 +0100
committerguy Decoux <ts@moulon.inra.fr>2009-02-28 20:04:27 +0100
commit5ddb005992b57f89ee974c22b89a91f06e7fc2e3 (patch)
treea43de752a32b5c263bccbcacd66d1d74b0f1918b
parent35a378406bed6a38e4797d7faefafa8c9738073e (diff)
downloadmmap-ruby-5ddb005992b57f89ee974c22b89a91f06e7fc2e3.zip
mmap-ruby-5ddb005992b57f89ee974c22b89a91f06e7fc2e3.tar.gz
mmap-0.1.1
-rwxr-xr-xb.rb31
-rw-r--r--mmap.c59
2 files changed, 71 insertions, 19 deletions
diff --git a/b.rb b/b.rb
index 6c685ca..2bc2475 100755
--- a/b.rb
+++ b/b.rb
@@ -1,5 +1,32 @@
#!/usr/bin/ruby
require "mmap"
+PAGESIZE = 4096
+f = File.open("aa", "w")
+f.write("\0" * PAGESIZE)
+f.write("b.rb")
+f.write("\0" * PAGESIZE)
+f.close
+m = Mmap.new("aa", "rw", "offset" => 0)
+p m.size == "b.rb".size + 2 * PAGESIZE
+p m.scan(/[a-z.]+/) == ["b.rb"]
+p m.index("b.rb") == PAGESIZE
+p m.rindex("b.rb") == PAGESIZE
+p m.sub!(/[a-z.]+/, "toto") == m
+p m.scan(/[a-z.]+/) == ["toto"]
+begin
+ m.sub!(/[a-z.]+/, "alpha")
+ puts "not OK must give an error"
+rescue
+ puts "OK : #$!"
+end
+m.munmap
m = Mmap.new("aa", "rw")
-m.gsub!(/(.)/, '(\&)')
-
+p m.index("toto") == PAGESIZE
+p m.sub!(/([a-z.]+)/, "alpha") == m
+p $& == "toto"
+p $1 == "toto"
+p m.index("toto") == nil
+p m.index("alpha") == PAGESIZE
+p m.size == 5 + 2 * PAGESIZE
+m.gsub!(/\0/, "X")
+p m.size == 5 + 2 * PAGESIZE
diff --git a/mmap.c b/mmap.c
index b6cf702..c3e055b 100644
--- a/mmap.c
+++ b/mmap.c
@@ -60,7 +60,8 @@ mm_free(t_mm)
#define MM_MODIFY 1
#define MM_ORIGIN 2
-#define MM_CHANGE 4
+#define MM_CHANGE (MM_MODIFY | 4)
+#define MM_PROTECT 8
#define MM_FROZEN 1
#define MM_FIXED 2
@@ -94,6 +95,16 @@ mm_unmap(obj)
}
static VALUE
+mm_freeze(obj)
+ VALUE obj;
+{
+ mm_mmap *t_mm;
+ rb_obj_freeze(obj);
+ GetMmap(obj, t_mm, 0);
+ t_mm->frozen |= MM_FROZEN;
+}
+
+static VALUE
mm_str(obj, modify)
VALUE obj;
int modify;
@@ -102,13 +113,23 @@ mm_str(obj, modify)
VALUE ret;
GetMmap(obj, t_mm, modify & ~MM_ORIGIN);
- ret = rb_tainted_str_new2("");
+ if (rb_obj_tainted(obj)) {
+ ret = rb_tainted_str_new2("");
+ }
+ else {
+ ret = rb_str_new2("");
+ }
if (t_mm->frozen & MM_FROZEN) ret = rb_obj_freeze(ret);
free(RSTRING(ret)->ptr);
RSTRING(ret)->ptr = t_mm->addr;
RSTRING(ret)->len = t_mm->real;
if (modify & MM_ORIGIN)
RSTRING(ret)->orig = ret;
+ if (modify & MM_MODIFY) {
+ if (OBJ_FROZEN(ret)) rb_error_frozen("mmap");
+ if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't modify mmap");
+ }
return ret;
}
@@ -226,8 +247,11 @@ mm_map(argc, argv, obj)
t_mm->smode = smode;
t_mm->path = ruby_strdup(path);
if (smode == O_RDONLY) {
- t_mm->frozen |= MM_FROZEN;
res = rb_obj_freeze(res);
+ t_mm->frozen |= MM_FROZEN;
+ }
+ else {
+ OBJ_TAINT(res);
}
return res;
}
@@ -349,8 +373,8 @@ mm_mprotect(obj, a)
else {
t_mm->smode == O_RDONLY;
if (t_mm->vscope == MAP_PRIVATE) {
- t_mm->frozen |= MM_FROZEN;
obj = rb_obj_freeze(obj);
+ t_mm->frozen |= MM_FROZEN;
}
}
}
@@ -595,9 +619,8 @@ mm_gsub_bang(argc, argv, obj)
}
if (OBJ_TAINTED(repl)) tainted = 1;
plen = END(0);
- if (RSTRING(val)->len > plen) {
+ if ((t_mm->real + RSTRING(val)->len - plen) > t_mm->len) {
mm_realloc(t_mm, RSTRING(str)->len + 2 * RSTRING(val)->len);
- t_mm->real += RSTRING(val)->len - plen;
RSTRING(str)->ptr = t_mm->addr;
}
if (RSTRING(val)->len != plen) {
@@ -611,6 +634,7 @@ mm_gsub_bang(argc, argv, obj)
memcpy(RSTRING(str)->ptr + start,
RSTRING(val)->ptr, RSTRING(val)->len);
RSTRING(str)->len += RSTRING(val)->len - plen;
+ t_mm->real = RSTRING(str)->len;
if (BEG(0) == END(0)) {
offset = start + END(0) + mbclen2(RSTRING(str)->ptr[END(0)], pat);
offset += RSTRING(val)->len - plen;
@@ -914,11 +938,7 @@ mm_bang_i(obj, flag, id, argc, argv)
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
}
str = mm_str(obj, flag);
- if (flag & MM_ORIGIN) {
- res = rb_funcall2(str, id, argc, argv);
- rb_gc_force_recycle(str);
- }
- else {
+ if (flag & MM_PROTECT) {
VALUE tmp[4];
tmp[0] = str;
tmp[1] = (VALUE)id;
@@ -926,6 +946,10 @@ mm_bang_i(obj, flag, id, argc, argv)
tmp[3] = (VALUE)argv;
res = rb_ensure(mm_protect_bang, (VALUE)tmp, mm_recycle, str);
}
+ else {
+ res = rb_funcall2(str, id, argc, argv);
+ rb_gc_force_recycle(str);
+ }
if (res == Qnil) return res;
GetMmap(obj, t_mm, 0);
t_mm->real = RSTRING(str)->len;
@@ -972,7 +996,7 @@ static VALUE
mm_chop_bang(a)
VALUE a;
{
- return mm_bang_i(a, MM_MODIFY | MM_CHANGE, rb_intern("chop!"), 0, 0);
+ return mm_bang_i(a, MM_CHANGE, rb_intern("chop!"), 0, 0);
}
static VALUE
@@ -987,7 +1011,7 @@ mm_chomp_bang(argc, argv, obj)
int argc;
VALUE *argv, obj;
{
- return mm_bang_i(obj, MM_MODIFY | MM_CHANGE, rb_intern("chomp!"), argc, argv);
+ return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("chomp!"), argc, argv);
}
static VALUE
@@ -995,7 +1019,7 @@ mm_delete_bang(argc, argv, obj)
int argc;
VALUE *argv, obj;
{
- return mm_bang_i(obj, MM_MODIFY | MM_CHANGE, rb_intern("delete!"), argc, argv);
+ return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("delete!"), argc, argv);
}
static VALUE
@@ -1003,7 +1027,7 @@ mm_squeeze_bang(argc, argv, obj)
int argc;
VALUE *argv, obj;
{
- return mm_bang_i(obj, MM_MODIFY | MM_CHANGE, rb_intern("squeeze!"), argc, argv);
+ return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("squeeze!"), argc, argv);
}
static VALUE
@@ -1013,7 +1037,7 @@ mm_tr_bang(obj, a, b)
VALUE tmp[2];
tmp[0] = a;
tmp[1] = b;
- return mm_bang_i(obj, MM_MODIFY, rb_intern("tr!"), 2, tmp);
+ return mm_bang_i(obj, MM_MODIFY | MM_PROTECT, rb_intern("tr!"), 2, tmp);
}
static VALUE
@@ -1023,7 +1047,7 @@ mm_tr_s_bang(obj, a, b)
VALUE tmp[2];
tmp[0] = a;
tmp[1] = b;
- return mm_bang_i(obj, MM_MODIFY | MM_CHANGE, rb_intern("tr_s!"), 2, tmp);
+ return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("tr_s!"), 2, tmp);
}
static VALUE
@@ -1193,6 +1217,7 @@ Init_mmap()
rb_define_method(mm_cMap, "protect", mm_mprotect, 1);
rb_define_method(mm_cMap, "madvise", mm_madvise, 1);
rb_define_method(mm_cMap, "extend", mm_extend, 1);
+ rb_define_method(mm_cMap, "freeze", mm_freeze, 1);
rb_define_method(mm_cMap, "clone", mm_undefined, -1);
rb_define_method(mm_cMap, "dup", mm_undefined, -1);
rb_define_method(mm_cMap, "<=>", mm_cmp, 1);