From 5e32ca78488cbfb34a7dc8881afae91c1571553f Mon Sep 17 00:00:00 2001 From: Hiroshi Shirosaki Date: Thu, 15 Mar 2012 21:49:05 +0900 Subject: [PATCH] Add specs for tainted String --- ext/fenix/file.c | 24 ++++++++++++++++++++++++ spec/fenix/file_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/ext/fenix/file.c b/ext/fenix/file.c index 052a16a..4ae2799 100644 --- a/ext/fenix/file.c +++ b/ext/fenix/file.c @@ -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 diff --git a/spec/fenix/file_spec.rb b/spec/fenix/file_spec.rb index c6321fc..ddd808f 100644 --- a/spec/fenix/file_spec.rb +++ b/spec/fenix/file_spec.rb @@ -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 }