mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	scanner: enforce correct argument type for enums
The scanner now checks whether arguments that have an associated <enum> have the right type. An argument with an enum attribute must be of type int or uint, and if the <enum> with that name has the bitfield attribute set to true, then the argument must be of type uint. Changes since v3: - Remove useless allow_null check - Switch to using bool - Clearer message on errorous input - Minor formatting fix Signed-off-by: Auke Booij <auke@tulcod.com> Reviewed-by: Bryce Harrington <bryce@osg.samsung.com> Reviewed-by: Nils Chr. Brause <nilschrbrause@googlemail.com>
This commit is contained in:
		
							parent
							
								
									851614fa78
								
							
						
					
					
						commit
						1771299a5a
					
				
					 1 changed files with 69 additions and 0 deletions
				
			
		| 
						 | 
					@ -128,6 +128,7 @@ struct arg {
 | 
				
			||||||
	char *interface_name;
 | 
						char *interface_name;
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
	char *summary;
 | 
						char *summary;
 | 
				
			||||||
 | 
						char *enumeration_name;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct enumeration {
 | 
					struct enumeration {
 | 
				
			||||||
| 
						 | 
					@ -136,6 +137,7 @@ struct enumeration {
 | 
				
			||||||
	struct wl_list entry_list;
 | 
						struct wl_list entry_list;
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
	struct description *description;
 | 
						struct description *description;
 | 
				
			||||||
 | 
						bool bitfield;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct entry {
 | 
					struct entry {
 | 
				
			||||||
| 
						 | 
					@ -540,6 +542,8 @@ start_element(void *data, const char *element_name, const char **atts)
 | 
				
			||||||
	const char *summary = NULL;
 | 
						const char *summary = NULL;
 | 
				
			||||||
	const char *since = NULL;
 | 
						const char *since = NULL;
 | 
				
			||||||
	const char *allow_null = NULL;
 | 
						const char *allow_null = NULL;
 | 
				
			||||||
 | 
						const char *enumeration_name = NULL;
 | 
				
			||||||
 | 
						const char *bitfield = NULL;
 | 
				
			||||||
	int i, version = 0;
 | 
						int i, version = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
 | 
						ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
 | 
				
			||||||
| 
						 | 
					@ -562,6 +566,10 @@ start_element(void *data, const char *element_name, const char **atts)
 | 
				
			||||||
			since = atts[i + 1];
 | 
								since = atts[i + 1];
 | 
				
			||||||
		if (strcmp(atts[i], "allow-null") == 0)
 | 
							if (strcmp(atts[i], "allow-null") == 0)
 | 
				
			||||||
			allow_null = atts[i + 1];
 | 
								allow_null = atts[i + 1];
 | 
				
			||||||
 | 
							if (strcmp(atts[i], "enum") == 0)
 | 
				
			||||||
 | 
								enumeration_name = atts[i + 1];
 | 
				
			||||||
 | 
							if (strcmp(atts[i], "bitfield") == 0)
 | 
				
			||||||
 | 
								bitfield = atts[i + 1];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx->character_data_length = 0;
 | 
						ctx->character_data_length = 0;
 | 
				
			||||||
| 
						 | 
					@ -655,6 +663,11 @@ start_element(void *data, const char *element_name, const char **atts)
 | 
				
			||||||
				     "allow-null is only valid for objects, strings, and arrays");
 | 
									     "allow-null is only valid for objects, strings, and arrays");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0)
 | 
				
			||||||
 | 
								arg->enumeration_name = NULL;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								arg->enumeration_name = xstrdup(enumeration_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (summary)
 | 
							if (summary)
 | 
				
			||||||
			arg->summary = xstrdup(summary);
 | 
								arg->summary = xstrdup(summary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -665,6 +678,16 @@ start_element(void *data, const char *element_name, const char **atts)
 | 
				
			||||||
			fail(&ctx->loc, "no enum name given");
 | 
								fail(&ctx->loc, "no enum name given");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		enumeration = create_enumeration(name);
 | 
							enumeration = create_enumeration(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (bitfield == NULL || strcmp(bitfield, "false") == 0)
 | 
				
			||||||
 | 
								enumeration->bitfield = false;
 | 
				
			||||||
 | 
							else if (strcmp(bitfield, "true") == 0)
 | 
				
			||||||
 | 
								enumeration->bitfield = true;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								fail(&ctx->loc,
 | 
				
			||||||
 | 
					                             "invalid value (%s) for bitfield attribute (only true/false are accepted)",
 | 
				
			||||||
 | 
					                             bitfield);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wl_list_insert(ctx->interface->enumeration_list.prev,
 | 
							wl_list_insert(ctx->interface->enumeration_list.prev,
 | 
				
			||||||
			       &enumeration->link);
 | 
								       &enumeration->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -700,6 +723,46 @@ start_element(void *data, const char *element_name, const char **atts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					verify_arguments(struct parse_context *ctx, struct wl_list *messages, struct wl_list *enumerations)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct message *m;
 | 
				
			||||||
 | 
						wl_list_for_each(m, messages, link) {
 | 
				
			||||||
 | 
							struct arg *a;
 | 
				
			||||||
 | 
							wl_list_for_each(a, &m->arg_list, link) {
 | 
				
			||||||
 | 
								struct enumeration *e, *f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!a->enumeration_name)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								f = NULL;
 | 
				
			||||||
 | 
								wl_list_for_each(e, enumerations, link) {
 | 
				
			||||||
 | 
									if(strcmp(e->name, a->enumeration_name) == 0)
 | 
				
			||||||
 | 
										f = e;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (f == NULL)
 | 
				
			||||||
 | 
									fail(&ctx->loc,
 | 
				
			||||||
 | 
									     "could not find enumeration %s",
 | 
				
			||||||
 | 
									     a->enumeration_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								switch (a->type) {
 | 
				
			||||||
 | 
								case INT:
 | 
				
			||||||
 | 
									if (f->bitfield)
 | 
				
			||||||
 | 
										fail(&ctx->loc,
 | 
				
			||||||
 | 
										     "bitfield-style enum must only be referenced by uint");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case UNSIGNED:
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									fail(&ctx->loc,
 | 
				
			||||||
 | 
									     "enumeration-style argument has wrong type");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
end_element(void *data, const XML_Char *name)
 | 
					end_element(void *data, const XML_Char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -723,6 +786,12 @@ end_element(void *data, const XML_Char *name)
 | 
				
			||||||
			     ctx->enumeration->name);
 | 
								     ctx->enumeration->name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx->enumeration = NULL;
 | 
							ctx->enumeration = NULL;
 | 
				
			||||||
 | 
						} else if (strcmp(name, "interface") == 0) {
 | 
				
			||||||
 | 
							struct interface *i = ctx->interface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							verify_arguments(ctx, &i->request_list, &i->enumeration_list);
 | 
				
			||||||
 | 
							verify_arguments(ctx, &i->event_list, &i->enumeration_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue