Rob Shearman : widl: Add checking to arguments of non-local functions.

Alexandre Julliard julliard at winehq.org
Mon Apr 14 07:14:30 CDT 2008


Module: wine
Branch: master
Commit: 2ac495c85d884548c053e0ed6aac78d128abdc08
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2ac495c85d884548c053e0ed6aac78d128abdc08

Author: Rob Shearman <rob at codeweavers.com>
Date:   Mon Apr 14 11:00:26 2008 +0100

widl: Add checking to arguments of non-local functions.

Check that out arguments have enough levels of indirection and that they 
don't derive from void * or a function pointer.

---

 tools/widl/parser.y |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 69 insertions(+), 1 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 0e5778d..fba941e 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -67,6 +67,8 @@
 
 unsigned char pointer_default = RPC_FC_UP;
 static int is_object_interface = FALSE;
+/* are we inside a library block? */
+static int is_inside_library = FALSE;
 
 typedef struct list typelist_t;
 struct typenode {
@@ -129,6 +131,7 @@ static int compute_method_indexes(type_t *iface);
 static char *gen_name(void);
 static void process_typedefs(var_list_t *names);
 static void check_arg(var_t *arg);
+static void check_functions(const type_t *iface);
 static void check_all_user_types(ifref_list_t *ifaces);
 static const attr_list_t *check_iface_attrs(const char *name, const attr_list_t *attrs);
 static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs);
@@ -391,10 +394,11 @@ library_start: attributes libraryhdr '{'	{ check_library_attrs($2, $1);
 						  if (!parse_only) start_typelib($2, $1);
 						  if (!parse_only && do_header) write_library($2, $1);
 						  if (!parse_only && do_idfile) write_libid($2, $1);
+						  is_inside_library = TRUE;
 						}
 	;
 librarydef: library_start imp_statements '}'
-	    semicolon_opt			{ if (!parse_only) end_typelib(); }
+	    semicolon_opt			{ if (!parse_only) end_typelib(); is_inside_library = FALSE; }
 	;
 
 m_args:						{ $$ = NULL; }
@@ -834,6 +838,7 @@ interfacedef: interfacehdr inherit
 	  '{' int_statements '}' semicolon_opt	{ $$ = $1.interface;
 						  $$->ref = $2;
 						  $$->funcs = $4;
+						  check_functions($$);
 						  compute_method_indexes($$);
 						  if (!parse_only && do_header) write_interface($$);
 						  if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
@@ -2354,6 +2359,69 @@ static const attr_list_t *check_coclass_attrs(const char *name, const attr_list_
   return attrs;
 }
 
+/* checks that arguments for a function make sense for marshalling and unmarshalling */
+static void check_remoting_args(const func_t *func)
+{
+    const char *funcname = func->def->name;
+    const var_t *arg;
+
+    if (func->args) LIST_FOR_EACH_ENTRY( arg, func->args, const var_t, entry )
+    {
+        int ptr_level = 0;
+        const type_t *type = arg->type;
+        int is_wire_marshal = 0;
+        int is_context_handle = 0;
+
+        /* get pointer level and fundamental type for the argument */
+        for (;;)
+        {
+            if (!is_wire_marshal && is_attr(type->attrs, ATTR_WIREMARSHAL))
+                is_wire_marshal = 1;
+            if (!is_context_handle && is_attr(type->attrs, ATTR_CONTEXTHANDLE))
+                is_context_handle = 1;
+            if (type->kind == TKIND_ALIAS)
+                type = type->orig;
+            else if (is_ptr(type))
+            {
+                ptr_level++;
+                type = type->ref;
+            }
+            else
+                break;
+        }
+
+        /* check that [out] parameters have enough pointer levels */
+        if (is_attr(arg->attrs, ATTR_OUT))
+        {
+            if (!is_array(type))
+            {
+                if (!ptr_level)
+                    error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname);
+                if (type->type == RPC_FC_IP && ptr_level == 1)
+                    error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname);
+            }
+        }
+
+        if (type->type == 0 && !is_attr(arg->attrs, ATTR_IIDIS) && !is_wire_marshal && !is_context_handle)
+            error_loc_info(&arg->loc_info, "parameter \'%s\' of function \'%s\' cannot derive from void *\n", arg->name, funcname);
+        else if (type->type == RPC_FC_FUNCTION)
+            error_loc_info(&arg->loc_info, "parameter \'%s\' of function \'%s\' cannot be a function pointer\n", arg->name, funcname);
+    }
+}
+
+static void check_functions(const type_t *iface)
+{
+    if (!is_inside_library && !is_attr(iface->attrs, ATTR_LOCAL))
+    {
+        const func_t *func;
+        if (iface->funcs) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry )
+        {
+            if (!is_attr(func->def->attrs, ATTR_LOCAL))
+                check_remoting_args(func);
+        }
+    }
+}
+
 static void check_all_user_types(ifref_list_t *ifrefs)
 {
   const ifref_t *ifref;




More information about the wine-cvs mailing list