Skip to content

Commit 8712d4f

Browse files
committed
Fix FFI crash when embedded struct/union is skipped.
visit_struct and visit_union pushed nil into version arrays when recursive calls returned nil (skipped, forward-declared, or opaque). This caused NoMethodError in merge_children when the nil shared a versioned bucket with non-nil entries.
1 parent 2597b10 commit 8712d4f

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

lib/ruby-bindgen/generators/ffi/ffi.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,18 @@ def visit_struct(cursor)
240240

241241
# Define any embedded structures
242242
cursor.find_by_kind(false, :cursor_struct).each do |struct|
243+
content = visit_struct(struct)
244+
next unless content
243245
version = @symbols.version(struct)
244-
result[version] << visit_struct(struct)
246+
result[version] << content
245247
end
246248

247249
# Define any embedded unions
248250
cursor.find_by_kind(false, :cursor_union).each do |union|
251+
content = visit_union(union)
252+
next unless content
249253
version = @symbols.version(union)
250-
result[version] << visit_union(union)
254+
result[version] << content
251255
end
252256

253257
# Define any embedded callbacks
@@ -311,14 +315,18 @@ def visit_union(cursor)
311315

312316
# Define any embedded unions
313317
cursor.find_by_kind(false, :cursor_union).each do |union|
318+
content = visit_union(union)
319+
next unless content
314320
version = @symbols.version(union)
315-
result[version] << visit_union(union)
321+
result[version] << content
316322
end
317323

318324
# Define any embedded structures
319325
cursor.find_by_kind(false, :cursor_struct).each do |struct|
326+
content = visit_struct(struct)
327+
next unless content
320328
version = @symbols.version(struct)
321-
result[version] << visit_struct(struct)
329+
result[version] << content
322330
end
323331

324332
# Define any embedded callbacks

test/bindings/c/filtering.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ class IncludedStruct < FFI::Struct
1515
)
1616

1717
typedef :int, :included_typedef
18+
19+
class ContainerStruct < FFI::Struct
20+
layout :member, SkippedEmbedded,
21+
:value, :int
22+
end
1823
end

test/ffi_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ def test_filtering
6060
"/internal_helper.*/",
6161
"SkippedStruct",
6262
"SkippedEnum",
63-
"SkippedTypedef"] })
63+
"SkippedTypedef",
64+
"SkippedEmbedded"] })
6465
end
6566

6667
def test_rename

test/headers/c/filtering.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,15 @@ typedef int SkippedTypedef;
6969

7070
// Normal typedef - should be INCLUDED
7171
typedef int IncludedTypedef;
72+
73+
// --- Embedded skipped struct ---
74+
75+
// Struct containing an embedded struct that is skipped
76+
struct ContainerStruct
77+
{
78+
struct SkippedEmbedded
79+
{
80+
int a;
81+
} member;
82+
int value;
83+
};

0 commit comments

Comments
 (0)