From 2092adeadc5493caaeddaecacfb13ff02f48cd2f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Aug 2010 11:14:52 +0200 Subject: [PATCH 1/2] pidl: Samba3/ClientNDR - Correctly copy arrays, if r.out.size < r.in.size. metze Signed-off-by: Andreas Schneider (similar to commit 33d1879d5b50e2d98c1bb13b835e7cfb178e3336) (similar to commit d1e92cd2944983ecabd0511ff7c8221c1033a3a8) Fixes bug #7607. --- pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm | 38 ++++++++++++++++++++++++++----- 1 files changed, 32 insertions(+), 6 deletions(-) diff --git a/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index a45abdb..a5052e2 100644 --- a/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -15,7 +15,7 @@ use strict; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property ParseExpr); use Parse::Pidl::Samba4 qw(DeclLong); -use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv); +use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); use vars qw($VERSION); $VERSION = '0.01'; @@ -95,12 +95,38 @@ sub ParseOutputArgument($$$) # Since the data is being copied into a user-provided data # structure, the user should be able to know the size beforehand # to allocate a structure of the right size. - my $env = GenerateFunctionInEnv($fn, "r."); - my $size_is = ParseExpr($e->{LEVELS}[$level]->{SIZE_IS}, $env, $e->{ORIGINAL}); - if (has_property($e, "charset")) { - $self->pidl("memcpy(discard_const_p(uint8_t *, $e->{NAME}), r.out.$e->{NAME}, ($size_is) * sizeof(*$e->{NAME}));"); + my $in_env = GenerateFunctionInEnv($fn, "r."); + my $out_env = GenerateFunctionOutEnv($fn, "r."); + my $l = $e->{LEVELS}[$level]; + unless (defined($l->{SIZE_IS})) { + $self->pidl('#error No size known for [out] array `$e->{NAME}'); + error($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'"); } else { - $self->pidl("memcpy($e->{NAME}, r.out.$e->{NAME}, ($size_is) * sizeof(*$e->{NAME}));"); + my $in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL}); + my $out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL}); + my $out_length_is = $out_size_is; + if (defined($l->{LENGTH_IS})) { + $out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL}); + } + if ($out_size_is ne $in_size_is) { + $self->pidl("if (($out_size_is) > ($in_size_is)) {"); + $self->indent; + $self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;"); + $self->deindent; + $self->pidl("}"); + } + if ($out_length_is ne $out_size_is) { + $self->pidl("if (($out_length_is) > ($out_size_is)) {"); + $self->indent; + $self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;"); + $self->deindent; + $self->pidl("}"); + } + if (has_property($e, "charset")) { + $self->pidl("memcpy(discard_const_p(uint8_t *, $e->{NAME}), r.out.$e->{NAME}, ($out_length_is) * sizeof(*$e->{NAME}));"); + } else { + $self->pidl("memcpy($e->{NAME}, r.out.$e->{NAME}, ($out_length_is) * sizeof(*$e->{NAME}));"); + } } } else { $self->pidl("*$e->{NAME} = *r.out.$e->{NAME};"); -- 1.7.0.4 From 5f0fa3727d51cacaf59080ee2870bcaae80adeab Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Aug 2010 11:26:03 +0200 Subject: [PATCH 2/2] rerun: make samba3-idl metze --- librpc/gen_ndr/cli_epmapper.c | 10 ++++++++-- librpc/gen_ndr/cli_ntsvcs.c | 10 ++++++++-- librpc/gen_ndr/cli_winreg.c | 21 ++++++++++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/librpc/gen_ndr/cli_epmapper.c b/librpc/gen_ndr/cli_epmapper.c index 65621d3..eef9139 100644 --- a/librpc/gen_ndr/cli_epmapper.c +++ b/librpc/gen_ndr/cli_epmapper.c @@ -135,7 +135,10 @@ NTSTATUS rpccli_epm_Lookup(struct rpc_pipe_client *cli, /* Return variables */ *entry_handle = *r.out.entry_handle; *num_ents = *r.out.num_ents; - memcpy(entries, r.out.entries, (r.in.max_ents) * sizeof(*entries)); + if ((*r.out.num_ents) > (r.in.max_ents)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(entries, r.out.entries, (*r.out.num_ents) * sizeof(*entries)); /* Return result */ return NT_STATUS_OK; @@ -184,7 +187,10 @@ NTSTATUS rpccli_epm_Map(struct rpc_pipe_client *cli, /* Return variables */ *entry_handle = *r.out.entry_handle; *num_towers = *r.out.num_towers; - memcpy(towers, r.out.towers, (r.in.max_towers) * sizeof(*towers)); + if ((*r.out.num_towers) > (r.in.max_towers)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(towers, r.out.towers, (*r.out.num_towers) * sizeof(*towers)); /* Return result */ return NT_STATUS_OK; diff --git a/librpc/gen_ndr/cli_ntsvcs.c b/librpc/gen_ndr/cli_ntsvcs.c index 8f98278..e9c3d4c 100644 --- a/librpc/gen_ndr/cli_ntsvcs.c +++ b/librpc/gen_ndr/cli_ntsvcs.c @@ -461,7 +461,10 @@ NTSTATUS rpccli_PNP_GetDeviceList(struct rpc_pipe_client *cli, } /* Return variables */ - memcpy(buffer, r.out.buffer, (*r.in.length) * sizeof(*buffer)); + if ((*r.out.length) > (*r.in.length)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(buffer, r.out.buffer, (*r.out.length) * sizeof(*buffer)); *length = *r.out.length; /* Return result */ @@ -606,7 +609,10 @@ NTSTATUS rpccli_PNP_GetDeviceRegProp(struct rpc_pipe_client *cli, /* Return variables */ *reg_data_type = *r.out.reg_data_type; - memcpy(buffer, r.out.buffer, (*r.in.buffer_size) * sizeof(*buffer)); + if ((*r.out.buffer_size) > (*r.in.buffer_size)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(buffer, r.out.buffer, (*r.out.buffer_size) * sizeof(*buffer)); *buffer_size = *r.out.buffer_size; *needed = *r.out.needed; diff --git a/librpc/gen_ndr/cli_winreg.c b/librpc/gen_ndr/cli_winreg.c index c5d19be..93f969d 100644 --- a/librpc/gen_ndr/cli_winreg.c +++ b/librpc/gen_ndr/cli_winreg.c @@ -544,7 +544,13 @@ NTSTATUS rpccli_winreg_EnumValue(struct rpc_pipe_client *cli, *type = *r.out.type; } if (value && r.out.value) { - memcpy(value, r.out.value, (*r.in.size) * sizeof(*value)); + if ((*r.out.size) > (*r.in.size)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + if ((*r.out.length) > (*r.out.size)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(value, r.out.value, (*r.out.length) * sizeof(*value)); } if (size && r.out.size) { *size = *r.out.size; @@ -915,7 +921,13 @@ NTSTATUS rpccli_winreg_QueryValue(struct rpc_pipe_client *cli, *type = *r.out.type; } if (data && r.out.data) { - memcpy(data, r.out.data, (*r.in.data_size) * sizeof(*data)); + if ((*r.out.data_size) > (*r.in.data_size)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + if ((*r.out.data_length) > (*r.out.data_size)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(data, r.out.data, (*r.out.data_length) * sizeof(*data)); } if (data_size && r.out.data_size) { *data_size = *r.out.data_size; @@ -1483,7 +1495,10 @@ NTSTATUS rpccli_winreg_QueryMultipleValues(struct rpc_pipe_client *cli, /* Return variables */ memcpy(values, r.out.values, (r.in.num_values) * sizeof(*values)); if (buffer && r.out.buffer) { - memcpy(buffer, r.out.buffer, (*r.in.buffer_size) * sizeof(*buffer)); + if ((*r.out.buffer_size) > (*r.in.buffer_size)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + memcpy(buffer, r.out.buffer, (*r.out.buffer_size) * sizeof(*buffer)); } *buffer_size = *r.out.buffer_size; -- 1.7.0.4