Skip to content

Commit 2d6c5a9

Browse files
cameroncookecodex
andcommitted
fix(build): Harden XCFramework validation scripts
Escape generated project string values consistently, replace Swift interface import matching with token parsing, and constrain generated Swift interface sanitization to type-like prefixes. This addresses review feedback without changing the binary distribution layout. Refs EME-1168 Co-Authored-By: OpenAI Codex <noreply@openai.com>
1 parent d112145 commit 2d6c5a9

3 files changed

Lines changed: 29 additions & 9 deletions

File tree

scripts/build_xcframework_distribution.rb

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,25 @@ def sanitize_swift_interfaces(modules_path, framework_name)
230230
FileUtils.rm_f(path)
231231
elsif path.end_with?(".swiftinterface")
232232
content = File.read(path)
233-
sanitized = content.lines.reject { |line| line.include?("NSInvocation") }.join
234-
sanitized = sanitized.gsub("XCTest.", "").gsub("#{framework_name}.", "")
235-
File.write(path, sanitized)
233+
File.write(path, sanitized_swift_interface(content, framework_name))
236234
end
237235
end
238236
end
239237

238+
def sanitized_swift_interface(content, framework_name)
239+
content.lines.each_with_object([]) do |line, sanitized_lines|
240+
next if line.include?("NSInvocation")
241+
242+
sanitized_lines << sanitize_swift_interface_line(line, framework_name)
243+
end.join
244+
end
245+
246+
def sanitize_swift_interface_line(line, framework_name)
247+
escaped_framework_name = Regexp.escape(framework_name)
248+
line.gsub(/\bXCTest\.(?=[A-Z_])/, "")
249+
.gsub(/\b#{escaped_framework_name}\.(?=[A-Z_])/, "")
250+
end
251+
240252
def create_xcframework(framework, archives_dir)
241253
output_path = XCFrameworkDistribution.distributed_xcframework_path(framework.name)
242254
FileUtils.rm_rf(output_path)

scripts/smoke_binary_integration_ios.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ def render_key(key)
212212
end
213213

214214
def quote(value)
215-
string = value.to_s
216-
"\"#{string.gsub('"', '\\"')}\""
215+
string = value.to_s.gsub("\\", "\\\\").gsub('"', '\\"')
216+
"\"#{string}\""
217217
end
218218

219219
def workspace

scripts/validate_xcframework_distribution.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,22 @@ def swift_module_dir(framework, framework_dir)
149149
def swift_interface_imports(interface_path)
150150
imports = Set.new
151151
File.foreach(interface_path) do |line|
152-
match = line.match(/^\s*(?:@[A-Za-z_][A-Za-z0-9_]*(?:\([^)]*\))?\s+|@_[A-Za-z_][A-Za-z0-9_]*(?:\([^)]*\))?\s+)*(?:(?:public|internal|package|private|fileprivate)\s+)?import\s+(?:(?:class|struct|enum|protocol|func|var|let|typealias)\s+)?([A-Za-z_][A-Za-z0-9_]*)/)
153-
next unless match
154-
155-
imports << match[1]
152+
module_name = swift_interface_import_module(line)
153+
imports << module_name unless module_name.nil?
156154
end
157155
imports
158156
end
159157

158+
def swift_interface_import_module(line)
159+
tokens = line.strip.split
160+
tokens.shift while tokens.first&.start_with?("@")
161+
tokens.shift while %w[public internal package private fileprivate].include?(tokens.first)
162+
return nil unless tokens.shift == "import"
163+
164+
tokens.shift if %w[class struct enum protocol func var let typealias].include?(tokens.first)
165+
tokens.first&.split(".")&.first
166+
end
167+
160168
def disallowed_interface_modules
161169
private_modules = FRAMEWORKS.flat_map(&:private_source_targets)
162170
(private_modules + EXTERNAL_PACKAGES.keys).to_set

0 commit comments

Comments
 (0)