[前][次][番号順一覧][スレッド一覧]

ruby-changes:19279

From: tenderlove <ko1@a...>
Date: Fri, 22 Apr 2011 04:18:19 +0900 (JST)
Subject: [ruby-changes:19279] Ruby:r31317 (trunk): * ext/psych/parser.c (parse): strings from psych have proper taint

tenderlove	2011-04-22 04:17:46 +0900 (Fri, 22 Apr 2011)

  New Revision: 31317

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31317

  Log:
    * ext/psych/parser.c (parse): strings from psych have proper taint
      markings.
    * test/psych/test_tainted.rb: test for string taint

  Added files:
    trunk/test/psych/test_tainted.rb
  Modified files:
    trunk/ChangeLog
    trunk/ext/psych/parser.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31316)
+++ ChangeLog	(revision 31317)
@@ -1,3 +1,10 @@
+Fri Apr 22 04:16:14 2011  Aaron Patterson <aaron@t...>
+
+	* ext/psych/parser.c (parse): strings from psych have proper taint
+	  markings.
+
+	* test/psych/test_tainted.rb: test for string taint
+
 Thu Apr 21 01:30:02 2011  NARUSE, Yui  <naruse@r...>
 
 	* random.c (rb_f_srand): fix rdoc: srand(0)'s 0 is a seed.
Index: ext/psych/parser.c
===================================================================
--- ext/psych/parser.c	(revision 31316)
+++ ext/psych/parser.c	(revision 31317)
@@ -73,6 +73,7 @@
     yaml_parser_t * parser;
     yaml_event_t event;
     int done = 0;
+    int tainted = 0;
 #ifdef HAVE_RUBY_ENCODING_H
     int encoding = rb_utf8_encindex();
     rb_encoding * internal_enc = rb_default_internal_encoding();
@@ -81,8 +82,11 @@
 
     Data_Get_Struct(self, yaml_parser_t, parser);
 
+    if (OBJ_TAINTED(yaml)) tainted = 1;
+
     if(rb_respond_to(yaml, id_read)) {
 	yaml_parser_set_input(parser, io_reader, (void *)yaml);
+	if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
     } else {
 	StringValue(yaml);
 	yaml_parser_set_input_string(
@@ -140,6 +144,7 @@
 			VALUE prefix = Qnil;
 			if(start->handle) {
 			    handle = rb_str_new2((const char *)start->handle);
+			    if (tainted) OBJ_TAINT(handle);
 #ifdef HAVE_RUBY_ENCODING_H
 			    PSYCH_TRANSCODE(handle, encoding, internal_enc);
 #endif
@@ -147,6 +152,7 @@
 
 			if(start->prefix) {
 			    prefix = rb_str_new2((const char *)start->prefix);
+			    if (tainted) OBJ_TAINT(prefix);
 #ifdef HAVE_RUBY_ENCODING_H
 			    PSYCH_TRANSCODE(prefix, encoding, internal_enc);
 #endif
@@ -171,6 +177,7 @@
 		VALUE alias = Qnil;
 		if(event.data.alias.anchor) {
 		    alias = rb_str_new2((const char *)event.data.alias.anchor);
+		    if (tainted) OBJ_TAINT(alias);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(alias, encoding, internal_enc);
 #endif
@@ -188,6 +195,7 @@
 		    (const char *)event.data.scalar.value,
 		    (long)event.data.scalar.length
 		    );
+		if (tainted) OBJ_TAINT(val);
 
 #ifdef HAVE_RUBY_ENCODING_H
 		PSYCH_TRANSCODE(val, encoding, internal_enc);
@@ -195,6 +203,7 @@
 
 		if(event.data.scalar.anchor) {
 		    anchor = rb_str_new2((const char *)event.data.scalar.anchor);
+		    if (tainted) OBJ_TAINT(anchor);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
 #endif
@@ -202,6 +211,7 @@
 
 		if(event.data.scalar.tag) {
 		    tag = rb_str_new2((const char *)event.data.scalar.tag);
+		    if (tainted) OBJ_TAINT(tag);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
 #endif
@@ -226,6 +236,7 @@
 		VALUE implicit, style;
 		if(event.data.sequence_start.anchor) {
 		    anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
+		    if (tainted) OBJ_TAINT(anchor);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
 #endif
@@ -234,6 +245,7 @@
 		tag = Qnil;
 		if(event.data.sequence_start.tag) {
 		    tag = rb_str_new2((const char *)event.data.sequence_start.tag);
+		    if (tainted) OBJ_TAINT(tag);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
 #endif
@@ -258,6 +270,7 @@
 		VALUE implicit, style;
 		if(event.data.mapping_start.anchor) {
 		    anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
+		    if (tainted) OBJ_TAINT(anchor);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
 #endif
@@ -265,6 +278,7 @@
 
 		if(event.data.mapping_start.tag) {
 		    tag = rb_str_new2((const char *)event.data.mapping_start.tag);
+		    if (tainted) OBJ_TAINT(tag);
 #ifdef HAVE_RUBY_ENCODING_H
 		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
 #endif
Index: test/psych/test_tainted.rb
===================================================================
--- test/psych/test_tainted.rb	(revision 0)
+++ test/psych/test_tainted.rb	(revision 31317)
@@ -0,0 +1,128 @@
+require 'psych/helper'
+
+module Psych
+  class TestStringTainted < TestCase
+    class Tainted < Handler
+      attr_reader :tc
+
+      def initialize tc
+        @tc = tc
+      end
+
+      def start_document version, tags, implicit
+        tags.flatten.each do |tag|
+          assert_taintedness tag
+        end
+      end
+
+      def alias name
+        assert_taintedness name
+      end
+
+      def scalar value, anchor, tag, plain, quoted, style
+        assert_taintedness value
+        assert_taintedness tag if tag
+        assert_taintedness anchor if anchor
+      end
+
+      def start_sequence anchor, tag, implicit, style
+        assert_taintedness tag if tag
+        assert_taintedness anchor if anchor
+      end
+
+      def start_mapping anchor, tag, implicit, style
+        assert_taintedness tag if tag
+        assert_taintedness anchor if anchor
+      end
+
+      def assert_taintedness thing, message = "'#{thing}' should be tainted"
+        tc.assert thing.tainted?, message
+      end
+    end
+
+    class Untainted < Tainted
+      def assert_taintedness thing, message = "'#{thing}' should not be tainted"
+        tc.assert !thing.tainted?, message
+      end
+    end
+
+
+    def setup
+      handler = Tainted.new self
+      @parser = Psych::Parser.new handler
+    end
+
+    def test_tags_are_tainted
+      assert_taintedness "%TAG !yaml! tag:yaml.org,2002:\n---\n!yaml!str \"foo\""
+    end
+
+    def test_alias
+      assert_taintedness  "--- &ponies\n- foo\n- *ponies"
+    end
+
+    def test_scalar
+      assert_taintedness "--- ponies"
+    end
+
+    def test_anchor
+      assert_taintedness "--- &hi ponies"
+    end
+
+    def test_scalar_tag
+      assert_taintedness "--- !str ponies"
+    end
+
+    def test_seq_start_tag
+      assert_taintedness "--- !!seq [ a ]"
+    end
+
+    def test_seq_start_anchor
+      assert_taintedness "--- &zomg [ a ]"
+    end
+
+    def test_seq_mapping_tag
+      assert_taintedness "--- !!map { a: b }"
+    end
+
+    def test_seq_mapping_anchor
+      assert_taintedness "--- &himom { a: b }"
+    end
+
+    def assert_taintedness string
+      @parser.parse string.taint
+    end
+  end
+
+  class TestStringUntainted < TestStringTainted
+    def setup
+      handler = Untainted.new self
+      @parser = Psych::Parser.new handler
+    end
+
+    def assert_taintedness string
+      @parser.parse string
+    end
+  end
+
+  class TestStringIOUntainted < TestStringTainted
+    def setup
+      handler = Untainted.new self
+      @parser = Psych::Parser.new handler
+    end
+
+    def assert_taintedness string
+      @parser.parse StringIO.new(string)
+    end
+  end
+
+  class TestIOTainted < TestStringTainted
+    def assert_taintedness string
+      t = Tempfile.new(['something', 'yml'])
+      t.binmode
+      t.write string
+      t.close
+      File.open(t.path) { |f| @parser.parse f }
+      t.close(true)
+    end
+  end
+end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]