Author: tridge
Date: 2004-12-10 22:16:35 +0000 (Fri, 10 Dec 2004)
New Revision: 4136

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=4136

Log:
when we have a size or switch variable that is a pointer we need to check that 
the server
hasn't given us a null pointer, otherwise we can segv when we dereference it. 
For example:

  [size_is(*size)] *x;
  uint32 *size;

if a broken server gave us x != NULL and size == NULL then we would crash. I've 
added 
a check_null_pointer() call in pidl to catch this.


Modified:
   branches/SAMBA_4_0/source/build/pidl/parser.pm


Changeset:
Modified: branches/SAMBA_4_0/source/build/pidl/parser.pm
===================================================================
--- branches/SAMBA_4_0/source/build/pidl/parser.pm      2004-12-10 21:31:32 UTC 
(rev 4135)
+++ branches/SAMBA_4_0/source/build/pidl/parser.pm      2004-12-10 22:16:35 UTC 
(rev 4136)
@@ -106,7 +106,18 @@
        die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
 }
 
+#####################################################################
+# check that a variable we get from find_size_var isn't a null pointer
+sub check_null_pointer($)
+{
+       my $size = shift;
+       if ($size =~ /^\*/) {
+               my $size2 = substr($size, 1);
+               pidl "\tif ($size2 == NULL) return 
NT_STATUS_INVALID_PARAMETER_MIX;\n";
+       }
+}
 
+
 #####################################################################
 # work out is a parse function should be declared static or not
 sub fn_prefix($)
@@ -277,11 +288,13 @@
 
        if (util::has_property($e, "size_is")) {
                my $size = find_size_var($e, util::array_size($e), $var_prefix);
+               check_null_pointer($size);
                pidl "\tNDR_CHECK(ndr_check_array_size(ndr, 
(void*)&$var_prefix$e->{NAME}, $size));\n";
        }
 
        if (my $length = util::has_property($e, "length_is")) {
                $length = find_size_var($e, $length, $var_prefix);
+               check_null_pointer($length);
                pidl "\tNDR_CHECK(ndr_check_array_length(ndr, 
(void*)&$var_prefix$e->{NAME}, $length));\n";
        }
 }
@@ -302,7 +315,7 @@
        # we allocate enough to pull the elements
        if (defined $e->{CONFORMANT_SIZE}) {
                $alloc_size = $e->{CONFORMANT_SIZE};
-
+               check_null_pointer($size);
                pidl "\tif ($size > $alloc_size) {\n";
                pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, 
\"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
                pidl "\t}\n";
@@ -337,6 +350,7 @@
                $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
        }
 
+       check_null_pointer($size);
        if (util::is_scalar_type($e->{TYPE})) {
                pidl "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, 
$var_prefix$e->{NAME}, $size));\n";
        } else {
@@ -431,6 +445,9 @@
        my $cprefix = util::c_pull_prefix($e);
 
        my $utype = $structs{$e->{TYPE}};
+
+       check_null_pointer($switch_var);
+
        if (!defined $utype ||
            !util::has_property($utype->{DATA}, "nodiscriminant")) {
                my $e2 = find_sibling($e, $switch);
@@ -473,6 +490,8 @@
        my $switch_var = find_size_var($e, $switch, $var_prefix);
        my $cprefix = util::c_push_prefix($e);
 
+       check_null_pointer($switch_var);
+
        my $utype = $structs{$e->{TYPE}};
        if (!defined $utype ||
            !util::has_property($utype->{DATA}, "nodiscriminant")) {
@@ -502,6 +521,8 @@
        my $switch_var = find_size_var($e, $switch, $var_prefix);
        my $cprefix = util::c_push_prefix($e);
 
+       check_null_pointer($switch_var);
+
        pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, 
$cprefix$var_prefix$e->{NAME});\n";
 }
 
@@ -718,6 +739,7 @@
        if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
                my $size = find_size_var($e, util::array_size($e), "r->");
                $e->{CONFORMANT_SIZE} = $size;
+               check_null_pointer($size);
                pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
        }
 
@@ -878,6 +900,7 @@
                        pidl "\tret = ndr_size_ptr(ret, &r->$e->{NAME}, flags); 
\n";
                } elsif (util::is_inline_array($e)) {
                        $sizevar = find_size_var($e, util::array_size($e), 
"r->");
+                       check_null_pointer($sizevar);
                        pidl "\t{\n";
                        pidl "\t\tint i;\n";
                        pidl "\t\tfor(i = 0; i < $sizevar; i++) {\n";
@@ -1399,6 +1422,7 @@
 
        # its an array
        my $size = find_size_var($e, $asize, "r->out.");
+       check_null_pointer($size);
        pidl "\tNDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);\n";
        if (util::has_property($e, "in")) {
                pidl "\tmemcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * 
sizeof(*r->in.$e->{NAME}));\n";

Reply via email to