@@ -69,60 +69,84 @@ typedef struct struct_dep {
6969} s_struct_dep ;
7070
7171/**
72- * Find all the dependencies from a given structure
72+ * Add a struct to the dependency list if not already present
7373 *
74- * @param[out] deps_count count of how many struct dependency pointers
75- * @param[in] first_dep pointer to the first dependency pointer
76- * @param[in] struct_ptr pointer to the struct we are getting the dependencies of
77- * @return pointer to the first found dependency, \ref NULL otherwise
74+ * @param[in,out] first_dep pointer to the head of the dependency list
75+ * @param[in] struct_ptr pointer to the struct to add
76+ * @return \ref true on success, \ref false on memory allocation failure
7877 */
79- static bool get_struct_dependencies (s_struct_dep * * first_dep , const s_struct_712 * struct_ptr ) {
80- const s_struct_712_field * field_ptr ;
81- const char * arg_structname ;
82- const s_struct_712 * arg_struct_ptr ;
78+ static bool add_dep_if_new (s_struct_dep * * first_dep , const s_struct_712 * struct_ptr ) {
8379 s_struct_dep * tmp ;
8480 s_struct_dep * new_dep ;
8581
82+ for (tmp = * first_dep ; tmp != NULL ; tmp = (s_struct_dep * ) ((flist_node_t * ) tmp )-> next ) {
83+ if (tmp -> s == struct_ptr ) return true;
84+ }
85+ if ((new_dep = APP_MEM_ALLOC (sizeof (* new_dep ))) == NULL ) {
86+ apdu_response_code = SWO_INSUFFICIENT_MEMORY ;
87+ return false;
88+ }
89+ new_dep -> s = struct_ptr ;
90+ flist_push_back ((flist_node_t * * ) first_dep , (flist_node_t * ) new_dep );
91+ return true;
92+ }
93+
94+ /**
95+ * Scan all fields of a struct and add any unknown TYPE_CUSTOM dependencies
96+ *
97+ * @param[in,out] first_dep pointer to the head of the dependency list
98+ * @param[in] struct_ptr pointer to the struct whose fields are scanned
99+ * @return \ref true on success, \ref false on error
100+ */
101+ static bool collect_direct_deps (s_struct_dep * * first_dep , const s_struct_712 * struct_ptr ) {
102+ const s_struct_712_field * field_ptr ;
103+ const s_struct_712 * dep ;
104+ const char * dep_name ;
105+
86106 for (field_ptr = struct_ptr -> fields ; field_ptr != NULL ;
87107 field_ptr = (s_struct_712_field * ) ((flist_node_t * ) field_ptr )-> next ) {
88108 if (field_ptr -> type == TYPE_CUSTOM ) {
89- // get struct name
90- arg_structname = get_struct_field_typename (field_ptr );
91- // from its name, get the pointer to its definition
92- if ((arg_struct_ptr = get_structn (arg_structname , strlen (arg_structname ))) == NULL ) {
93- PRINTF ("Error: could not find EIP-712 dependency struct \"" );
94- for (int i = 0 ; i < (int ) strlen (arg_structname ); ++ i )
95- PRINTF ("%c" , arg_structname [i ]);
96- PRINTF ("\" during type_hash\n" );
109+ dep_name = get_struct_field_typename (field_ptr );
110+ if ((dep = get_structn (dep_name , strlen (dep_name ))) == NULL ) {
111+ PRINTF ("Error: could not find EIP-712 dependency struct \"%s\" during type_hash\n" ,
112+ dep_name );
97113 return false;
98114 }
99-
100- // check if it is not already present in the dependencies array
101- for (tmp = * first_dep ; tmp != NULL ;
102- tmp = (s_struct_dep * ) ((flist_node_t * ) tmp )-> next ) {
103- // it's a match!
104- if (tmp -> s == arg_struct_ptr ) {
105- break ;
106- }
107- }
108- // if it's not present in the array, add it and recurse into it
109- if (tmp == NULL ) {
110- if (APP_MEM_CALLOC ((void * * ) & new_dep , sizeof (s_struct_dep )) == false) {
111- apdu_response_code = SWO_INSUFFICIENT_MEMORY ;
112- return false;
113- }
114- new_dep -> s = arg_struct_ptr ;
115- flist_push_back ((flist_node_t * * ) first_dep , (flist_node_t * ) new_dep );
116- // TODO: Move away from recursive calls
117- if (!get_struct_dependencies (first_dep , arg_struct_ptr )) {
118- return false;
119- }
115+ if (!add_dep_if_new (first_dep , dep )) {
116+ return false;
120117 }
121118 }
122119 }
123120 return true;
124121}
125122
123+ /**
124+ * Find all the transitive dependencies of a given structure
125+ *
126+ * Uses the dependency list itself as a worklist: new entries are appended at
127+ * the back while the cursor advances forward, so newly discovered dependencies
128+ * are processed without recursion and without extra allocations.
129+ *
130+ * @param[out] first_dep pointer to the head of the dependency list
131+ * @param[in] struct_ptr pointer to the struct we are getting the dependencies of
132+ * @return \ref true on success, \ref false on error
133+ */
134+ static bool get_struct_dependencies (s_struct_dep * * first_dep , const s_struct_712 * struct_ptr ) {
135+ s_struct_dep * cursor ;
136+
137+ if (!collect_direct_deps (first_dep , struct_ptr )) {
138+ return false;
139+ }
140+
141+ for (cursor = * first_dep ; cursor != NULL ;
142+ cursor = (s_struct_dep * ) ((flist_node_t * ) cursor )-> next ) {
143+ if (!collect_direct_deps (first_dep , cursor -> s )) {
144+ return false;
145+ }
146+ }
147+ return true;
148+ }
149+
126150static bool compare_struct_deps (const s_struct_dep * a , const s_struct_dep * b ) {
127151 const char * name1 , * name2 ;
128152 size_t namelen1 , namelen2 ;
0 commit comments