r7195: - Fix echo pipe
authorJelmer Vernooij <jelmer@samba.org>
Thu, 2 Jun 2005 13:21:11 +0000 (13:21 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:25 +0000 (13:17 -0500)
- Don't allocate strings
- Give higher preference to the [out] part of variables when they
  are being used by another [out] variable. Also make sure that
  [in] variables never use [out] variables (i.e. switch_is() on an
  [in] variable can no longer use an [out] variable).
(This used to be commit 837c83d77a2d1990419c4f3e343616daf8da5799)

source4/build/pidl/ndr_parser.pm
source4/rpc_server/echo/rpc_echo.c
source4/torture/rpc/echo.c

index 60000430419af74be4f7e8a18b3ea0673c9a6a07..473aa94f1301e7c08c6f71bcc2b76d498e9087e0 100644 (file)
@@ -208,7 +208,21 @@ sub GenerateStructEnv($)
        return \%env;
 }
 
-sub GenerateFunctionEnv($)
+sub GenerateFunctionInEnv($)
+{
+       my $fn = shift;
+       my %env;
+
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               if (grep (/in/, @{$e->{DIRECTION}})) {
+                       $env{$e->{NAME}} = "r->in.$e->{NAME}";
+               }
+       }
+
+       return \%env;
+}
+
+sub GenerateFunctionOutEnv($)
 {
        my $fn = shift;
        my %env;
@@ -216,8 +230,7 @@ sub GenerateFunctionEnv($)
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep (/out/, @{$e->{DIRECTION}})) {
                        $env{$e->{NAME}} = "r->out.$e->{NAME}";
-               }
-               if (grep (/in/, @{$e->{DIRECTION}})) {
+               } elsif (grep (/in/, @{$e->{DIRECTION}})) {
                        $env{$e->{NAME}} = "r->in.$e->{NAME}";
                }
        }
@@ -1031,13 +1044,15 @@ sub ParsePtrPull($$$$)
 
        my $nl = Ndr::GetNextLevel($e, $l);
        my $next_is_array = ($nl->{TYPE} eq "ARRAY");
+       my $next_is_string = (($nl->{TYPE} eq "DATA") and 
+                                                ($nl->{DATA_TYPE} eq "string"));
 
        if ($l->{POINTER_TYPE} eq "ref") {
                unless ($l->{LEVEL} eq "TOP") {
                        pidl "NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));";
                }
 
-               unless ($next_is_array) {
+               unless ($next_is_array or $next_is_string) {
                        pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
                        pidl "\tNDR_ALLOC($ndr, $var_name);"; 
                        pidl "}";
@@ -1052,7 +1067,7 @@ sub ParsePtrPull($$$$)
 
        # Don't do this for arrays, they're allocated at the actual level 
        # of the array
-       unless ($next_is_array) { 
+       unless ($next_is_array or $next_is_string) { 
                pidl "NDR_ALLOC($ndr, $var_name);"; 
        } else {
                pidl "NDR_ALLOC_SIZE($ndr, $var_name, 1);"; # FIXME: Yes, this is nasty. We allocate an array twice - once just to indicate that  it's there, then the real allocation...
@@ -1861,8 +1876,6 @@ sub ParseFunctionPrint($)
 
        return if util::has_property($fn, "noprint");
 
-       my $env = GenerateFunctionEnv($fn);
-
        pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
@@ -1883,6 +1896,8 @@ sub ParseFunctionPrint($)
        pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
        pidl "ndr->depth++;";
 
+       my $env = GenerateFunctionInEnv($fn);
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep(/in/,@{$e->{DIRECTION}})) {
                        ParseElementPrint($e, "r->in.$e->{NAME}", $env);
@@ -1896,6 +1911,8 @@ sub ParseFunctionPrint($)
        indent;
        pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
        pidl "ndr->depth++;";
+
+       $env = GenerateFunctionOutEnv($fn);
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep(/out/,@{$e->{DIRECTION}})) {
                        ParseElementPrint($e, "r->out.$e->{NAME}", $env);
@@ -1922,8 +1939,6 @@ sub ParseFunctionPush($)
 
        return if util::has_property($fn, "nopush");
 
-       my $env = GenerateFunctionEnv($fn);
-
        pidl fn_prefix($fn) . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
@@ -1935,6 +1950,8 @@ sub ParseFunctionPush($)
        pidl "if (flags & NDR_IN) {";
        indent;
 
+       my $env = GenerateFunctionInEnv($fn);
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep(/in/,@{$e->{DIRECTION}})) {
                        ParseElementPush($e, "ndr", "r->in.", $env, 1, 1);
@@ -1947,6 +1964,7 @@ sub ParseFunctionPush($)
        pidl "if (flags & NDR_OUT) {";
        indent;
 
+       $env = GenerateFunctionOutEnv($fn);
        foreach my $e (@{$fn->{ELEMENTS}}) {
                if (grep(/out/,@{$e->{DIRECTION}})) {
                        ParseElementPush($e, "ndr", "r->out.", $env, 1, 1);
@@ -2001,8 +2019,6 @@ sub ParseFunctionPull($)
 
        return if util::has_property($fn, "nopull");
 
-       my $env = GenerateFunctionEnv($fn);
-
        # pull function args
        pidl fn_prefix($fn) . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
        pidl "{";
@@ -2028,6 +2044,8 @@ sub ParseFunctionPull($)
                last;
        }
 
+       my $env = GenerateFunctionInEnv($fn);
+
        foreach my $e (@{$fn->{ELEMENTS}}) {
                next unless (grep(/in/, @{$e->{DIRECTION}}));
                ParseElementPull($e, "ndr", "r->in.", $env, 1, 1);
@@ -2040,7 +2058,8 @@ sub ParseFunctionPull($)
                next unless (grep(/out/, @{$e->{DIRECTION}}));
                next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and 
                             $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
-
+               next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and 
+                                ($e->{LEVELS}[1]->{DATA_TYPE} eq "string"));
 
                if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
                        my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
@@ -2070,6 +2089,7 @@ sub ParseFunctionPull($)
        pidl "if (flags & NDR_OUT) {";
        indent;
 
+       $env = GenerateFunctionOutEnv($fn);
        foreach my $e (@{$fn->{ELEMENTS}}) {
                next unless grep(/out/, @{$e->{DIRECTION}});
                ParseElementPull($e, "ndr", "r->out.", $env, 1, 1);
index 057d89a866fcc1459ae98982a4dcbc9e8a2ebf5a..b67c17257930dba6eab3d414840ea55b4752f659 100644 (file)
@@ -56,6 +56,9 @@ static NTSTATUS echo_SinkData(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 static NTSTATUS echo_SourceData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_SourceData *r)
 {
        int i;
+
+       r->out.data = talloc_array(mem_ctx, uint8_t, r->in.len);
+       
        for (i=0;i<r->in.len;i++) {
                r->out.data[i] = i;
        }
index 14bfe573ce536252aa54f785548e374c0aaaba98..96a716a312db7b9261f7e61495727f36bbaa3f96 100644 (file)
@@ -107,15 +107,11 @@ static BOOL test_sourcedata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        int i;
        NTSTATUS status;
        int len = 200000 + (random() % 5000);
-       uint8_t *data_out;
        struct echo_SourceData r;
 
        printf("\nTesting SourceData\n");
 
-       data_out = talloc_size(mem_ctx, len);
-
        r.in.len = len;
-       r.out.data = data_out;
 
        status = dcerpc_echo_SourceData(p, mem_ctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
@@ -124,9 +120,9 @@ static BOOL test_sourcedata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        }
 
        for (i=0;i<len;i++) {
-               uint8_t *v = (uint8_t *)data_out;
+               uint8_t *v = (uint8_t *)r.out.data;
                if (v[i] != (i & 0xFF)) {
-                       printf("bad data 0x%x at %d\n", (uint8_t)data_out[i], i);
+                       printf("bad data 0x%x at %d\n", (uint8_t)r.out.data[i], i);
                        return False;
                }
        }
@@ -199,6 +195,7 @@ static BOOL test_testcall2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 
        for (i=1;i<=7;i++) {
                r.in.level = i;
+               r.out.info = talloc(mem_ctx, union echo_Info);
 
                printf("\nTesting TestCall2 level %d\n", i);
                status = dcerpc_echo_TestCall2(p, mem_ctx, &r);