Permalink
Browse files

Implement rb_str_modify(), and rb_check_safe_obj()

  • Loading branch information...
1 parent ba7af62 commit 2ce4caf3a754dde001e5d384efbee0a1ec3643b2 Wayne Meissner committed Mar 5, 2012
Showing with 145 additions and 17 deletions.
  1. +46 −3 cext/src/include/ruby/ruby.h
  2. +87 −0 cext/src/safe.cpp
  3. +12 −0 cext/src/string.cpp
  4. +0 −14 cext/src/util.cpp
@@ -291,6 +291,23 @@ RUBY_DLLSPEC void xfree(void*);
#define TYPE(x) rb_type((VALUE)(x))
#define CLASS_OF(x) rb_class_of((VALUE)(x))
+#define RB_TYPE_P(obj, type) ( \
+ ((type) == T_FIXNUM) ? FIXNUM_P(obj) : \
+ ((type) == T_TRUE) ? ((obj) == Qtrue) : \
+ ((type) == T_FALSE) ? ((obj) == Qfalse) : \
+ ((type) == T_NIL) ? ((obj) == Qnil) : \
+ ((type) == T_UNDEF) ? ((obj) == Qundef) : \
+ ((type) == T_SYMBOL) ? SYMBOL_P(obj) : \
+ (!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == (type)))
+
+#ifdef __GNUC__
+#define rb_type_p(obj, type) \
+ __extension__ (__builtin_constant_p(type) ? RB_TYPE_P((obj), (type)) : \
+ rb_type(obj) == (type))
+#else
+#define rb_type_p(obj, type) (rb_type(obj) == (type))
+#endif
+
/** The length of string str. */
#define RSTRING_LEN(str) jruby_str_length((str))
@@ -304,6 +321,35 @@ RUBY_DLLSPEC void xfree(void*);
#define StringValuePtr(v) rb_string_value_ptr(&(v))
#define StringValueCStr(str) rb_string_value_cstr(&(str))
+RUBY_DLLSPEC void rb_check_safe_obj(VALUE);
+RUBY_DLLSPEC void rb_check_safe_str(VALUE);
+#define SafeStringValue(v) do {\
+ StringValue(v);\
+ rb_check_safe_obj(v);\
+} while (0)
+/* obsolete macro - use SafeStringValue(v) */
+#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
+
+RUBY_DLLSPEC VALUE rb_str_export(VALUE);
+#define ExportStringValue(v) do {\
+ SafeStringValue(v);\
+ (v) = rb_str_export(v);\
+} while (0)
+RUBY_DLLSPEC VALUE rb_str_export_locale(VALUE);
+
+RUBY_DLLSPEC VALUE rb_get_path(VALUE);
+#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v))
+
+RUBY_DLLSPEC VALUE rb_get_path_no_checksafe(VALUE);
+#define FilePathStringValue(v) ((v) = rb_get_path_no_checksafe(v))
+
+RUBY_DLLSPEC void rb_secure(int);
+RUBY_DLLSPEC int rb_safe_level(void);
+RUBY_DLLSPEC void rb_set_safe_level(int);
+RUBY_DLLSPEC void rb_set_safe_level_force(int);
+RUBY_DLLSPEC void rb_secure_update(VALUE);
+RUBY_DLLSPEC NORETURN(void rb_insecure_operation(void));
+
/** The length of the array. */
#define RARRAY_LEN(ary) RARRAY(ary)->len
/** Returns a pointer to a VALUE[] that mirrors the data in
@@ -397,9 +443,6 @@ RUBY_DLLSPEC VALUE rb_exc_new2(VALUE, const char*);
RUBY_DLLSPEC VALUE rb_exc_new3(VALUE, VALUE);
RUBY_DLLSPEC VALUE rb_exc_raise(VALUE);
-RUBY_DLLSPEC void rb_secure(int);
-RUBY_DLLSPEC int rb_safe_level(void);
-
RUBY_DLLSPEC void rb_num_zerodiv(void);
RUBY_DLLSPEC long rb_num2long(VALUE);
RUBY_DLLSPEC unsigned long rb_num2ulong(VALUE);
View
@@ -0,0 +1,87 @@
+
+/**********************************************************************
+
+ safe.c -
+
+ $Author: nobu $
+ created at: Tue Sep 23 09:44:32 JST 2008
+
+ Copyright (C) 2008 Yukihiro Matsumoto
+
+**********************************************************************/
+
+/* safe-level:
+ 0 - strings from streams/environment/ARGV are tainted (default)
+ 1 - no dangerous operation by tainted value
+ 2 - process/file operations prohibited
+ 3 - all generated objects are tainted
+ 4 - no global (non-tainted) variable modification/no direct output
+*/
+
+#include "jruby.h"
+#include "ruby.h"
+#include "JLocalEnv.h"
+
+using namespace jruby;
+
+#define rb_frame_callee() (0)
+
+extern "C" int
+rb_safe_level(void)
+{
+ return FIX2INT(rb_gv_get("$SAFE"));
+}
+
+extern "C" void
+rb_secure(int level)
+{
+ if (level <= rb_safe_level()) {
+ if (rb_frame_callee()) {
+ rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
+ rb_id2name(rb_frame_callee()), rb_safe_level());
+ }
+ else {
+ rb_raise(rb_eSecurityError, "Insecure operation at level %d",
+ rb_safe_level());
+ }
+ }
+}
+
+extern "C" void
+rb_secure_update(VALUE obj)
+{
+ if (!OBJ_TAINTED(obj))
+ rb_secure(4);
+}
+
+extern "C" void
+rb_insecure_operation(void)
+{
+ if (rb_frame_callee()) {
+ rb_raise(rb_eSecurityError, "Insecure operation - %s",
+ rb_id2name(rb_frame_callee()));
+ }
+ else {
+ rb_raise(rb_eSecurityError, "Insecure operation: -r");
+ }
+}
+
+
+extern "C" void
+rb_check_safe_obj(VALUE x)
+{
+ if (rb_safe_level() > 0 && OBJ_TAINTED(x)) {
+ rb_insecure_operation();
+ }
+ rb_secure(4);
+}
+
+extern "C" void
+rb_check_safe_str(VALUE x)
+{
+ rb_check_safe_obj(x);
+ if (!RB_TYPE_P(x, T_STRING)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
+ rb_obj_classname(x));
+ }
+}
View
@@ -526,3 +526,15 @@ rb_str2cstr(VALUE str, long* len)
return cstr;
}
+
+
+extern "C" void
+rb_str_modify(VALUE str)
+{
+ JLocalEnv env;
+ jmethodID mid = getCachedMethodID(env, RubyString_class, "modify", "()V");
+
+ env->CallVoidMethod(valueToObject(env, str), mid);
+ checkExceptions(env);
+}
+
View
@@ -126,17 +126,3 @@ rb_scan_args(int argc, const VALUE* argv, const char* spec, ...)
rb_raise(rb_eFatal, "bad scan arg format: %s", spec);
return 0;
}
-
-extern "C" int
-rb_safe_level()
-{
- return FIX2INT(rb_gv_get("$SAFE"));
-}
-
-extern "C" void
-rb_secure(int level)
-{
- if (level <= rb_safe_level()) {
- rb_raise(rb_eSecurityError, "Insecure operation at level %d", rb_safe_level());
- }
-}

0 comments on commit 2ce4caf

Please sign in to comment.