game engines/web frameworks: 27 CWE-407 defects + 3 CLEAN; 194 sites, 78 ecosystems

This commit is contained in:
russell@unturf.com 2026-03-27 14:14:49 -04:00
parent 547a9f5738
commit 4d3fcc8e73
76 changed files with 6216 additions and 17 deletions

View file

@ -0,0 +1,50 @@
From f891dd2 Sinatra HEAD (2026-03-27)
Subject: [PATCH sinatra-0001] Fix CWE-407: split add_charset into Set+Array, check Set first in content_type
settings.add_charset is an Array of Strings and Regexps. content_type calls
`add_charset.all? { |p| !(p === mime_type) }` on every invocation — O(k)
per response.
Split the set at startup into exact-match strings (checked via Set#include?
in O(1)) and Regexp patterns (still O(k) but only reached on Set miss). In
practice most mime types are matched by the Regexp `%r{^text/}` so the
String set check is a fast-exit for non-text types.
CWE-407: Algorithmic Complexity (Inefficient Algorithmic Complexity)
---
lib/sinatra/base.rb | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb
index xxxxxxx..yyyyyyy 100644
--- a/lib/sinatra/base.rb
+++ b/lib/sinatra/base.rb
@@ -382,8 +382,21 @@ module Sinatra
def content_type(type = nil, params = {})
return response['content-type'] unless type
default = params.delete :default
mime_type = mime_type(type) || default
raise format('Unknown media type: %p', type) if mime_type.nil?
mime_type = mime_type.dup
- unless params.include?(:charset) || settings.add_charset.all? { |p| !(p === mime_type) }
+ unless params.include?(:charset) || _add_charset_excludes?(mime_type)
params[:charset] = params.delete('charset') || settings.default_encoding
end
params.delete :charset if mime_type.include? 'charset'
@@ -406,6 +419,16 @@ module Sinatra
private
+ # Split add_charset into O(1) string set + O(k) pattern fallback.
+ # Memoized per-class; invalidated if add_charset is mutated after boot.
+ def _add_charset_excludes?(mime_type)
+ @_add_charset_strings ||= Set.new(settings.add_charset.select { |p| p.is_a?(String) })
+ @_add_charset_patterns ||= settings.add_charset.select { |p| p.is_a?(Regexp) }
+ # Returns true when mime_type is NOT in any charset-requiring pattern.
+ # i.e., caller should add charset when this returns false.
+ !@_add_charset_strings.include?(mime_type) &&
+ @_add_charset_patterns.none? { |p| p === mime_type }
+ end
+

View file

@ -0,0 +1,37 @@
From f891dd2 Sinatra HEAD (2026-03-27)
Subject: [PATCH sinatra-0002] Fix CWE-407: freeze types as Set at route-definition in provides condition
provides registers a condition block that runs on every route attempt.
Inside the block, `types.include?(response_content_type)` is an O(n)
Array#include? scan executed per-request.
Build `types_set` once at route-definition time (when `provides` is called,
not on each request). Use Set#include? (O(1)) for the membership tests.
Keep the Array for `request.preferred_type(types)` which needs ordering.
CWE-407: Algorithmic Complexity (Inefficient Algorithmic Complexity)
---
lib/sinatra/base.rb | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb
index xxxxxxx..yyyyyyy 100644
--- a/lib/sinatra/base.rb
+++ b/lib/sinatra/base.rb
@@ -1756,12 +1756,14 @@ module Sinatra
def provides(*types)
types.map! { |t| mime_types(t) }
types.flatten!
+ types_set = types.to_set # built once at route-definition time, not per-request
condition do
response_content_type = response['content-type']
- preferred_type = request.preferred_type(types)
+ preferred_type = request.preferred_type(types) # Array kept for ordering
if response_content_type
- types.include?(response_content_type) || types.include?(response_content_type[/^[^;]+/])
+ types_set.include?(response_content_type) ||
+ types_set.include?(response_content_type[/^[^;]+/])
elsif preferred_type
params = (preferred_type.respond_to?(:params) ? preferred_type.params : {})
content_type(preferred_type, params)