@@ -53,6 +53,7 @@ namespace boost
53
53
54
54
namespace read_graphviz_detail
55
55
{
56
+ static const long max_subgraph_nesting_level = 255 ;
56
57
struct token
57
58
{
58
59
enum token_type
@@ -207,7 +208,7 @@ namespace read_graphviz_detail
207
208
208
209
tokenizer (const std::string& str) : begin(str.begin()), end(str.end())
209
210
{
210
- std::string end_of_token = " (?=(?:\\ W))" ;
211
+ // std::string end_of_token = "(?=(?:\\W))"; // SEHE: unused?
211
212
std::string whitespace = " (?:\\ s+)" ;
212
213
std::string slash_slash_comment = " (?://.*?$)" ;
213
214
std::string slash_star_comment = " (?:/\\ *.*?\\ */)" ;
@@ -527,6 +528,7 @@ namespace read_graphviz_detail
527
528
std::map< subgraph_name, subgraph_info > subgraphs;
528
529
std::string current_subgraph_name;
529
530
int sgcounter; // Counter for anonymous subgraphs
531
+ long sgnesting_level;
530
532
std::set< std::pair< node_name, node_name > >
531
533
existing_edges; // Used for checking in strict graphs
532
534
@@ -538,7 +540,7 @@ namespace read_graphviz_detail
538
540
subgraph_member_list& current_members () { return current ().members ; }
539
541
540
542
parser (const std::string& gr, parser_result& result)
541
- : the_tokenizer(gr), lookahead(), r(result), sgcounter(0 )
543
+ : the_tokenizer(gr), lookahead(), r(result), sgcounter(0 ), sgnesting_level( 0 )
542
544
{
543
545
current_subgraph_name = " ___root___" ;
544
546
current () = subgraph_info (); // Initialize root graph
@@ -773,10 +775,18 @@ namespace read_graphviz_detail
773
775
bool is_anonymous = true ;
774
776
if (first_token.type == token::kw_subgraph)
775
777
{
776
- if (peek ().type == token::identifier )
778
+ switch (peek ().type )
777
779
{
780
+ case token::identifier:
778
781
name = get ().normalized_value ;
779
782
is_anonymous = false ;
783
+ break ;
784
+ case token::left_brace:
785
+ is_anonymous = true ;
786
+ break ;
787
+ default :
788
+ error (" Subgraph reference needs a name" );
789
+ break ;
780
790
}
781
791
}
782
792
if (is_anonymous)
@@ -790,25 +800,30 @@ namespace read_graphviz_detail
790
800
= current (); // Initialize properties and defaults
791
801
subgraphs[name].members .clear (); // Except member list
792
802
}
793
- if (first_token.type == token::kw_subgraph
794
- && peek ().type != token::left_brace)
803
+ if (!is_anonymous && peek ().type != token::left_brace)
795
804
{
796
- if (is_anonymous)
797
- error (" Subgraph reference needs a name" );
798
805
return name;
799
806
}
800
807
subgraph_name old_sg = current_subgraph_name;
808
+ if (++sgnesting_level > max_subgraph_nesting_level)
809
+ {
810
+ error (" Exceeded maximum subgraph nesting level" );
811
+ }
801
812
current_subgraph_name = name;
802
- if (peek ().type == token::left_brace)
803
- get ();
804
- else
805
- error (" Wanted left brace to start subgraph" );
813
+ if (first_token.type != token::left_brace)
814
+ {
815
+ if (peek ().type == token::left_brace)
816
+ get ();
817
+ else
818
+ error (" Wanted left brace to start subgraph" );
819
+ }
806
820
parse_stmt_list ();
807
821
if (peek ().type == token::right_brace)
808
822
get ();
809
823
else
810
824
error (" Wanted right brace to end subgraph" );
811
825
current_subgraph_name = old_sg;
826
+ sgnesting_level -= 1 ;
812
827
return name;
813
828
}
814
829
0 commit comments