widl [2/2]: Improve pointer null checking logic

Dan Hipschman dsh at linux.ucla.edu
Fri Aug 11 19:33:40 CDT 2006


This fixes some faulty logic used to determine when pointer types may be
NULL.  It works with typedefs and when attributes are attached to types
instead of just variables.  MIDL also allows different pointer types and
chooses the last one as the actual value.  For example:

typedef [ptr] char *ptr_t;
typedef [ref] ptr_t ref_t;
int Foo([unique] ref_t p);

p will be [unique].

ChangeLog:
* Improve logic for when to perform null checks on pointer types
---
 tools/widl/client.c    |   22 +++++++--------------
 tools/widl/proxy.c     |   50 +++++++++++++++++++++++++++++++++++++++++++++---
 tools/widl/widltypes.h |    2 ++
 3 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/tools/widl/client.c b/tools/widl/client.c
index 79a4283..267bbfe 100644
--- a/tools/widl/client.c
+++ b/tools/widl/client.c
@@ -83,7 +83,6 @@ static void print_message_buffer_size(co
 static void check_pointers(const func_t *func)
 {
     var_t *var;
-    int pointer_type;
 
     if (!func->args)
         return;
@@ -92,21 +91,14 @@ static void check_pointers(const func_t 
     while (NEXT_LINK(var)) var = NEXT_LINK(var);
     while (var)
     {
-        pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
-        if (!pointer_type)
-            pointer_type = RPC_FC_RP;
-
-        if (pointer_type == RPC_FC_RP)
+        if (is_pointer(var) && cant_be_null(var))
         {
-            if (var->ptr_level >= 1)
-            {
-                print_client("if (!%s)\n", var->name);
-                print_client("{\n");
-                indent++;
-                print_client("RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
-                indent--;
-                print_client("}\n\n");
-            }
+            print_client("if (!%s)\n", var->name);
+            print_client("{\n");
+            indent++;
+            print_client("RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
+            indent--;
+            print_client("}\n\n");
         }
 
         var = PREV_LINK(var);
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c
index 5750159..9bba5c5 100644
--- a/tools/widl/proxy.c
+++ b/tools/widl/proxy.c
@@ -181,20 +181,64 @@ static void clear_output_vars( var_t *ar
   }
 }
 
-static int is_pointer(var_t *arg)
+int is_pointer(var_t *arg)
 {
   if (arg->ptr_level)
     return 1;
-  if (arg->type->type == RPC_FC_FP )
+
+  switch (ref_type(arg->type))
+  {
+  case RPC_FC_RP:
+  case RPC_FC_C_CSTRING:
+  case RPC_FC_C_WSTRING:
+  case RPC_FC_FP:
+  case RPC_FC_OP:
+  case RPC_FC_UP:
     return 1;
+  }
+
   return 0;
 }
 
+int cant_be_null(var_t *v)
+{
+  /* Search backwards for the most recent pointer attribute.  */
+  const attr_t *attrs = v->attrs;
+  const type_t *type = v->type;
+
+  if (! attrs && type)
+  {
+    attrs = type->attrs;
+    type = type->ref;
+  }
+
+  while (attrs)
+  {
+    int t = get_attrv(attrs, ATTR_POINTERTYPE);
+
+    if (t == RPC_FC_FP || t == RPC_FC_OP || t == RPC_FC_UP)
+      return 0;
+
+    if (t == RPC_FC_RP)
+      return 1;
+
+    if (type)
+    {
+      attrs = type->attrs;
+      type = type->ref;
+    }
+    else
+      attrs = NULL;
+  }
+
+  return 1;                             /* Default is RPC_FC_RP.  */
+}
+
 static void proxy_check_pointers( var_t *arg )
 {
   END_OF_LIST(arg);
   while (arg) {
-    if (is_pointer(arg)) {
+    if (is_pointer(arg) && cant_be_null(arg)) {
         print_proxy( "if(!%s)\n", arg->name );
         indent++;
         print_proxy( "RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 926a3e2..d39def3 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -299,5 +299,7 @@ struct _typelib_t {
 
 /* Get the actual type field for a type (chase down typedef references).  */
 unsigned char ref_type(const type_t *type);
+int is_pointer(var_t *v);
+int cant_be_null(var_t *v);
 
 #endif



More information about the wine-patches mailing list