Permalink
Browse files

Add specs for tainted String

  • Loading branch information...
1 parent db3eaed commit 5e32ca78488cbfb34a7dc8881afae91c1571553f @shirosaki committed Mar 15, 2012
Showing with 44 additions and 0 deletions.
  1. +24 −0 ext/fenix/file.c
  2. +20 −0 spec/fenix/file_spec.rb
View
@@ -408,10 +408,14 @@ fenix_file_expand_path(int argc, VALUE *argv)
wchar_t path_drive = L'\0', dir_drive = L'\0';
int ignore_dir = 0;
rb_encoding *path_encoding;
+ int tainted = 0;
// retrieve path and dir from argv
rb_scan_args(argc, argv, "11", &path, &dir);
+ /* tainted if path is tainted */
+ tainted = OBJ_TAINTED(path);
+
// get path encoding
if (NIL_P(dir)) {
path_encoding = rb_enc_get(path);
@@ -432,6 +436,9 @@ fenix_file_expand_path(int argc, VALUE *argv)
/* determine if we need the user's home directory */
if ((wpath_len == 1 && wpath_pos[0] == L'~') ||
(wpath_len >= 2 && wpath_pos[0] == L'~' && IS_DIR_SEPARATOR_P(wpath_pos[1]))) {
+ /* tainted if expanding '~' */
+ tainted = 1;
+
// wprintf(L"wpath requires expansion.\n");
whome = fenix_home_dir();
if (whome == NULL) {
@@ -473,6 +480,9 @@ fenix_file_expand_path(int argc, VALUE *argv)
wchar_t *pos = wuser;
char *user;
+ /* tainted if expanding '~' */
+ tainted = 1;
+
while (!IS_DIR_SEPARATOR_P(*pos) && *pos != '\0')
pos++;
@@ -574,6 +584,10 @@ fenix_file_expand_path(int argc, VALUE *argv)
}
if (wdir_len) {
+ /* tainted if dir is used and dir is tainted */
+ if (!tainted && OBJ_TAINTED(dir))
+ tainted = 1;
+
// wprintf(L"Copying wdir...\n");
wcsncpy(buffer_pos, wdir, wdir_len);
buffer_pos += wdir_len;
@@ -603,6 +617,12 @@ fenix_file_expand_path(int argc, VALUE *argv)
/* Ensure buffer is NULL terminated */
buffer_pos[0] = L'\0';
+
+ /* tainted if path is relative */
+ if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 && IS_DIR_UNC_P(buffer))) {
+ tainted = 1;
+ }
+
// wprintf(L"buffer: '%s'\n", buffer);
// FIXME: Make this more robust
@@ -656,6 +676,10 @@ fenix_file_expand_path(int argc, VALUE *argv)
/* convert to VALUE and set the path encoding */
result = rb_enc_str_new(fullpath, size - 1, path_encoding);
+
+ /* makes the result object tainted if expanding tainted strings or returning modified path */
+ if (tainted)
+ OBJ_TAINT(result);
}
// TODO: better cleanup
@@ -121,6 +121,26 @@
subject.expand_path('/foo').must_match %r"\A#{drive}/foo\z"i
end
+ it "returns tainted strings or not" do
+ subject.expand_path('foo').tainted?.must_equal true
+ subject.expand_path('foo'.taint).tainted?.must_equal true
+ subject.expand_path('/foo'.taint).tainted?.must_equal true
+ subject.expand_path('C:/foo'.taint).tainted?.must_equal true
+ subject.expand_path('/foo').tainted?.must_equal true
+ subject.expand_path('C:/foo').tainted?.must_equal false
+ subject.expand_path('//foo').tainted?.must_equal false
+ subject.expand_path('foo', 'bar').tainted?.must_equal true
+ subject.expand_path('foo', '/bar'.taint).tainted?.must_equal true
+ subject.expand_path('foo', 'C:/bar'.taint).tainted?.must_equal true
+ subject.expand_path('foo'.taint, '/bar').tainted?.must_equal true
+ subject.expand_path('foo'.taint, 'C:/bar').tainted?.must_equal true
+ subject.expand_path('foo', '/bar').tainted?.must_equal true
+ subject.expand_path('foo', 'C:/bar').tainted?.must_equal false
+ subject.expand_path('foo', '//bar').tainted?.must_equal false
+ subject.expand_path('~').tainted?.must_equal true
+ subject.expand_path('C:/foo/../bar').tainted?.must_equal false
+ end
+
describe "~/" do
let(:home) { "C:/UserHome" }
let(:home_drive) { nil }

0 comments on commit 5e32ca7

Please sign in to comment.