Skip to content

Commit 82a8d7e

Browse files
Fix gensairpc.pl crash on Doxygen 1.9.8+ by reusing NeedsTwoPassProcessing (#2282)
Why: To fix below build error Uncaught exception from user code: at gensairpc.pl line 480. main::assign_attr_types(HASH(0x55e190dc20c8), ARRAY(0x55e190d2d080)) called at gensairpc.pl line 434 main::get_definitions() called at gensairpc.pl line 156 main::assign_attr_types(HASH(0x55e190dc20c8), ARRAY(0x55e190d2d080)) called at gensairpc.pl line 434 main::get_definitions() called at gensairpc.pl line 156 How: gensairpc.pl crashed during SAI thrift build with an uncaught exception at line 480 (assign_attr_types) because its inline Doxygen layout detection was too weak - it only checked sai_8h.xml for any enumvalue presence, missing cases where the new Doxygen 1.9.8+ XML structure requires group__*.xml files to be processed for complete definitions. This caused incomplete parsing, leading to missing types and a croak in assign_attr_types when sai_attribute_value_t could not be found. Changes: - xmlutils.pm: Add NeedsTwoPassProcessing and export it. - parse.pl: Remove local NeedsTwoPassProcessing; use imported version. - gensairpc.pl: Replace inline detection with NeedsTwoPassProcessing() call, fixing the build failure and eliminating code duplication. Signed-off-by: Pavan Naregundi <pnaregundi@marvell.com>
1 parent 3eb1414 commit 82a8d7e

3 files changed

Lines changed: 114 additions & 103 deletions

File tree

meta/gensairpc.pl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,18 @@ sub get_definitions {
377377
my %apis;
378378
my $i = 0;
379379

380-
# Iterate over files
381-
for ( GetSaiXmlFiles($XMLDIR) ) {
380+
my @xml_files = GetSaiXmlFiles($XMLDIR);
381+
if (NeedsTwoPassProcessing())
382+
{
383+
unshift @xml_files, GetGroupXmlFiles($XMLDIR);
384+
}
385+
386+
for ( @xml_files )
387+
{
382388
my $xml = ReadXml($_);
383389

390+
next unless defined $xml->{compounddef}[0];
391+
384392
# Iterate over definitions
385393
for ( @{ $xml->{compounddef}[0]->{sectiondef} } ) {
386394
if ( $_->{kind} eq 'typedef' or $_->{kind} eq 'enum' ) {

meta/parse.pl

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -5298,107 +5298,6 @@ sub CreateSourcePragmaPop
52985298
WriteSource "#pragma GCC diagnostic pop";
52995299
}
53005300

5301-
sub NeedsTwoPassProcessing
5302-
{
5303-
#
5304-
# Detect if XML files require two-pass processing based on their structure.
5305-
#
5306-
# In Doxygen 1.9.8+, the XML structure changed:
5307-
# - sai_*.xml files have empty enum/define sections (just sectiondef exists, no memberdefs)
5308-
# - group_*.xml files contain the actual enum definitions with enumvalues and defines
5309-
#
5310-
# In older Doxygen versions:
5311-
# - sai_*.xml files contain both defines and enums with enumvalues
5312-
# - group_*.xml files don't exist or aren't used
5313-
#
5314-
# Returns 1 if two-pass processing is needed (new structure):
5315-
# - First pass: process all defines from group_*.xml files
5316-
# - Second pass: process enums/typedefs/functions from group_*.xml and sai_*.xml files
5317-
#
5318-
# Returns 0 if single-pass processing is sufficient (old structure):
5319-
# - Process sai_*.xml files only
5320-
#
5321-
5322-
my $sai_file = "$XMLDIR/sai_8h.xml";
5323-
5324-
my $saiacl_file = "$XMLDIR/saiacl_8h.xml";
5325-
5326-
return 1 if not -f $sai_file or not -f $saiacl_file;
5327-
5328-
#
5329-
# Check sai_8h.xml for enumvalue with name="SAI_API_SWITCH"
5330-
#
5331-
5332-
my $sai_ref = ReadXml $sai_file;
5333-
5334-
return 1 if not defined $sai_ref->{compounddef}[0];
5335-
5336-
my @sai_sections = @{ $sai_ref->{compounddef}[0]->{sectiondef} };
5337-
5338-
my $has_enumvalue = 0;
5339-
5340-
for my $section (@sai_sections)
5341-
{
5342-
next if not $section->{kind} eq "enum";
5343-
5344-
for my $memberdef (@{ $section->{memberdef} })
5345-
{
5346-
next if not $memberdef->{kind} eq "enum";
5347-
5348-
if (defined $memberdef->{enumvalue})
5349-
{
5350-
for my $enumvalue (@{ $memberdef->{enumvalue} })
5351-
{
5352-
if (defined $enumvalue->{name} and defined $enumvalue->{name}[0] and $enumvalue->{name}[0] eq "SAI_API_SWITCH")
5353-
{
5354-
$has_enumvalue = 1;
5355-
5356-
last;
5357-
}
5358-
}
5359-
}
5360-
}
5361-
5362-
last if $has_enumvalue;
5363-
}
5364-
5365-
#
5366-
# Check saiacl_8h.xml for memberdef kind="define"
5367-
#
5368-
5369-
my $saiacl_ref = ReadXml $saiacl_file;
5370-
5371-
return 1 if not defined $saiacl_ref->{compounddef}[0];
5372-
5373-
my @saiacl_sections = @{ $saiacl_ref->{compounddef}[0]->{sectiondef} };
5374-
5375-
my $has_define = 0;
5376-
5377-
for my $section (@saiacl_sections)
5378-
{
5379-
next if not $section->{kind} eq "define";
5380-
5381-
for my $memberdef (@{ $section->{memberdef} })
5382-
{
5383-
if ($memberdef->{kind} eq "define")
5384-
{
5385-
$has_define = 1;
5386-
5387-
last;
5388-
}
5389-
}
5390-
5391-
last if $has_define;
5392-
}
5393-
5394-
#
5395-
# If sai_8h.xml has enumvalues and saiacl_8h.xml has defines, it's old structure (single-pass)
5396-
# Otherwise, use two-pass processing (group_*.xml files contain the actual content)
5397-
#
5398-
5399-
return not ($has_enumvalue and $has_define);
5400-
}
5401-
54025301
sub ProcessXmlFiles
54035302
{
54045303
if (NeedsTwoPassProcessing())

meta/xmlutils.pm

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,109 @@ sub ExtractStructInfoEx
568568
return %Struct;
569569
}
570570

571+
sub NeedsTwoPassProcessing
572+
{
573+
#
574+
# Detect if XML files require two-pass processing based on their structure.
575+
#
576+
# In Doxygen 1.9.8+, the XML structure changed:
577+
# - sai_*.xml files have empty enum/define sections (just sectiondef exists, no memberdefs)
578+
# - group_*.xml files contain the actual enum definitions with enumvalues and defines
579+
#
580+
# In older Doxygen versions:
581+
# - sai_*.xml files contain both defines and enums with enumvalues
582+
# - group_*.xml files don't exist or aren't used
583+
#
584+
# Returns 1 if two-pass processing is needed (new structure):
585+
# - First pass: process all defines from group_*.xml files
586+
# - Second pass: process enums/typedefs/functions from group_*.xml and sai_*.xml files
587+
#
588+
# Returns 0 if single-pass processing is sufficient (old structure):
589+
# - Process sai_*.xml files only
590+
#
591+
592+
my $XMLDIR = $main::XMLDIR;
593+
594+
my $sai_file = "$XMLDIR/sai_8h.xml";
595+
596+
my $saiacl_file = "$XMLDIR/saiacl_8h.xml";
597+
598+
return 1 if not -f $sai_file or not -f $saiacl_file;
599+
600+
#
601+
# Check sai_8h.xml for enumvalue with name="SAI_API_SWITCH"
602+
#
603+
604+
my $sai_ref = ReadXml $sai_file;
605+
606+
return 1 if not defined $sai_ref->{compounddef}[0];
607+
608+
my @sai_sections = @{ $sai_ref->{compounddef}[0]->{sectiondef} };
609+
610+
my $has_enumvalue = 0;
611+
612+
for my $section (@sai_sections)
613+
{
614+
next if not $section->{kind} eq "enum";
615+
616+
for my $memberdef (@{ $section->{memberdef} })
617+
{
618+
next if not $memberdef->{kind} eq "enum";
619+
620+
if (defined $memberdef->{enumvalue})
621+
{
622+
for my $enumvalue (@{ $memberdef->{enumvalue} })
623+
{
624+
if (defined $enumvalue->{name} and defined $enumvalue->{name}[0] and $enumvalue->{name}[0] eq "SAI_API_SWITCH")
625+
{
626+
$has_enumvalue = 1;
627+
628+
last;
629+
}
630+
}
631+
}
632+
}
633+
634+
last if $has_enumvalue;
635+
}
636+
637+
#
638+
# Check saiacl_8h.xml for memberdef kind="define"
639+
#
640+
641+
my $saiacl_ref = ReadXml $saiacl_file;
642+
643+
return 1 if not defined $saiacl_ref->{compounddef}[0];
644+
645+
my @saiacl_sections = @{ $saiacl_ref->{compounddef}[0]->{sectiondef} };
646+
647+
my $has_define = 0;
648+
649+
for my $section (@saiacl_sections)
650+
{
651+
next if not $section->{kind} eq "define";
652+
653+
for my $memberdef (@{ $section->{memberdef} })
654+
{
655+
if ($memberdef->{kind} eq "define")
656+
{
657+
$has_define = 1;
658+
659+
last;
660+
}
661+
}
662+
663+
last if $has_define;
664+
}
665+
666+
#
667+
# If sai_8h.xml has enumvalues and saiacl_8h.xml has defines, it's old structure (single-pass)
668+
# Otherwise, use two-pass processing (group_*.xml files contain the actual content)
669+
#
670+
671+
return not ($has_enumvalue and $has_define);
672+
}
673+
571674
sub ExtractDescription
572675
{
573676
my ($type, $value, $item) = @_;
@@ -636,6 +739,7 @@ BEGIN
636739
our @ISA = qw(Exporter);
637740
our @EXPORT = qw/
638741
ReadXml UnescapeXml GetSaiXmlFiles GetXmlUnionFiles GetGroupXmlFiles
742+
NeedsTwoPassProcessing
639743
ExtractDescription ExtractStructInfo ExtractStructInfoEx
640744
/;
641745
}

0 commit comments

Comments
 (0)