[DRE-commits] [chef] 02/03: json_create_CVE-2013-0269_workaround

Antonio Terceiro terceiro at moszumanska.debian.org
Sat Jun 13 18:47:30 UTC 2015


This is an automated email from the git hooks/post-receive script.

terceiro pushed a commit to branch patch-queue/debian/wheezy
in repository chef.

commit 8d856b98f87b4bf3f0f83d74886560f10980bd8e
Author: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers at lists.alioth.debian.org>
Date:   Sat Feb 21 23:58:35 2015 -0200

    json_create_CVE-2013-0269_workaround
---
 lib/chef/cookbook_version.rb |  2 +-
 lib/chef/json_compat.rb      | 98 +++++++++++++++++++++++++++++++++++++++++++-
 lib/chef/resource.rb         | 18 ++++++++
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 1c2deef..c7c9503 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -807,7 +807,7 @@ class Chef
       cookbook_version.manifest = o
 
       # We don't need the following step when we decide to stop supporting deprecated operators in the metadata (e.g. <<, >>)
-      cookbook_version.manifest["metadata"] = JSON.parse(cookbook_version.metadata.to_json)
+      cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(cookbook_version.metadata.to_json)
 
       cookbook_version.freeze_version if o["frozen?"]
       cookbook_version
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb
index 9f59a41..4e14a11 100644
--- a/lib/chef/json_compat.rb
+++ b/lib/chef/json_compat.rb
@@ -24,6 +24,22 @@ class Chef
   class JSONCompat
     JSON_MAX_NESTING = 1000
 
+    JSON_CLASS = "json_class".freeze
+
+    CHEF_APICLIENT          = "Chef::ApiClient".freeze
+    CHEF_CHECKSUM           = "Chef::Checksum".freeze
+    CHEF_COOKBOOKVERSION    = "Chef::CookbookVersion".freeze
+    CHEF_DATABAG            = "Chef::DataBag".freeze
+    CHEF_DATABAGITEM        = "Chef::DataBagItem".freeze
+    CHEF_ENVIRONMENT        = "Chef::Environment".freeze
+    CHEF_NODE               = "Chef::Node".freeze
+    CHEF_ROLE               = "Chef::Role".freeze
+    CHEF_SANDBOX            = "Chef::Sandbox".freeze
+    CHEF_RESOURCE           = "Chef::Resource".freeze
+    CHEF_RESOURCECOLLECTION = "Chef::ResourceCollection".freeze
+    CHEF_WEBUIUSER          = "Chef::WebUIUser".freeze
+    CHEF_OPENIDREGISTRAION  = "Chef::OpenIDRegistration".freeze
+
     class <<self
       # See CHEF-1292/PL-538. Increase the max nesting for JSON, which defaults
       # to 19, and isn't enough for some (for example, a Node within a Node)
@@ -38,7 +54,49 @@ class Chef
 
       # Just call the JSON gem's parse method with a modified :max_nesting field
       def from_json(source, opts = {})
-        ::JSON.parse(source, opts_add_max_nesting(opts))
+        obj = ::Yajl::Parser.parse(source)
+
+        unless obj.kind_of?(Hash) || obj.kind_of?(Array)
+          raise JSON::ParserError, "Top level JSON object must be a Hash or Array (actual: #{obj.class})"
+        end
+
+        # The old default in the json gem (which we are mimicing because we
+        # sadly rely on this misfeature) is to "create additions" i.e., convert
+        # JSON objects into ruby objects. Explicit :create_additions => false
+        # is required to turn it off.
+        if opts[:create_additions].nil? || opts[:create_additions]
+          map_to_rb_obj(obj)
+        else
+          obj
+        end
+      rescue Yajl::ParseError => e
+        raise JSON::ParserError, e.message
+      end
+
+      # Look at an object that's a basic type (from json parse) and convert it
+      # to an instance of Chef classes if desired.
+      def map_to_rb_obj(json_obj)
+        res = case json_obj
+        when Hash
+          mapped_hash = map_hash_to_rb_obj(json_obj)
+          if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS]))
+            class_to_inflate.json_create(mapped_hash)
+          else
+            mapped_hash
+          end
+        when Array
+          json_obj.map {|e| map_to_rb_obj(e) }
+        else
+          json_obj
+        end
+        res
+      end
+
+      def map_hash_to_rb_obj(json_hash)
+        json_hash.each do |key, value|
+          json_hash[key] = map_to_rb_obj(value)
+        end
+        json_hash
       end
 
       def to_json(obj, opts = nil)
@@ -48,6 +106,44 @@ class Chef
       def to_json_pretty(obj, opts = nil)
         ::JSON.pretty_generate(obj, opts_add_max_nesting(opts))
       end
+
+
+      def class_for_json_class(json_class)
+        case json_class
+        when CHEF_APICLIENT
+          Chef::ApiClient
+        when CHEF_CHECKSUM
+          Chef::Checksum
+        when CHEF_COOKBOOKVERSION
+          Chef::CookbookVersion
+        when CHEF_DATABAG
+          Chef::DataBag
+        when CHEF_DATABAGITEM
+          Chef::DataBagItem
+        when CHEF_ENVIRONMENT
+          Chef::Environment
+        when CHEF_NODE
+          Chef::Node
+        when CHEF_ROLE
+          Chef::Role
+        when CHEF_SANDBOX
+          Chef::Sandbox
+        when CHEF_RESOURCE
+          Chef::Resource
+        when CHEF_RESOURCECOLLECTION
+          Chef::ResourceCollection
+        when CHEF_WEBUIUSER
+          Chef::WebUIUser
+        when CHEF_OPENIDREGISTRAION
+          Chef::OpenIDRegistration
+        when /^Chef::Resource/
+          Chef::Resource.find_subclass_by_name(json_class)
+        else
+          raise JSON::ParserError, "Unsupported `json_class` type '#{json_class}'"
+        end
+      end
+
     end
   end
 end
+
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 2fd3942..b8f7603 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -74,6 +74,24 @@ F
     FORBIDDEN_IVARS = [:@run_context, :@node, :@not_if, :@only_if]
     HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@node]
 
+    # Track all subclasses of Resource. This is used so names can be looked up
+    # when attempting to deserialize from JSON. (See: json_compat)
+    def self.resource_classes
+      @resource_classes ||= []
+    end
+
+    # Callback when subclass is defined. Adds subclass to list of subclasses.
+    def self.inherited(subclass)
+      resource_classes << subclass
+    end
+
+    # Look up a subclass by +class_name+ which should be a string that matches
+    # `Subclass.name`
+    def self.find_subclass_by_name(class_name)
+      resource_classes.first {|c| c.name == class_name }
+    end
+
+
     include Chef::Mixin::CheckHelper
     include Chef::Mixin::ParamsValidate
     include Chef::Mixin::Language

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/chef.git



More information about the Pkg-ruby-extras-commits mailing list