From d220237b19f361a2c3c09b292e11f54c8d522fdf Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 5 Oct 2005 00:29:47 +0000 Subject: r10721: Handle allocations and primitive / deferred data correctly. In theory, the generated output for DFS should work now (it compiles cleanly, but I haven't tested it yet). Not supported: - subcontexts() - relative pointers - unions of pointers - DATA_BLOB - several other things Also still need to do: - Remove some spurious spaces in the output - Do range() checking Example output is still available at http://samba.org/~jelmer/pidl_samba3/ (This used to be commit e2d7e382bb645f1bddd2047669bed10f121b59d2) --- source4/pidl/lib/Parse/Pidl/Samba3/Header.pm | 1 + source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm | 286 +++++++++++++++++++++------ source4/pidl/lib/Parse/Pidl/Samba3/Types.pm | 69 ++++--- 3 files changed, 273 insertions(+), 83 deletions(-) (limited to 'source4/pidl') diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm index 21a56e4c2d..5b7fddc14f 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm @@ -37,6 +37,7 @@ sub ParseElement($) } if ($l->{IS_VARYING}) { pidl "\tuint32 length_$e->{NAME};"; + pidl "\tuint32 offset_$e->{NAME};"; } } } diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm index 166d98bfb1..702835c378 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm @@ -14,6 +14,9 @@ use Parse::Pidl::Samba3::Types qw(DeclShort DeclLong InitType DissectType); use vars qw($VERSION); $VERSION = '0.01'; +use constant PRIMITIVES => 1; +use constant DEFERRED => 2; + my $res = ""; my $tabs = ""; sub indent() { $tabs.="\t"; } @@ -22,17 +25,22 @@ sub pidl($) { $res .= $tabs.(shift)."\n"; } sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); } #TODO: -# - Different scalars / buffers functions for arrays + unions -# - Memory allocation for arrays +# - Add some security checks (array sizes, memory alloc == NULL, etc) +# - Don't add seperate _p and _d functions if there is no deferred data -sub DeclareArrayVariables($) +sub DeclareArrayVariables { my $es = shift; + my $what = shift; my $output = 0; foreach my $e (@$es) { foreach my $l (@{$e->{LEVELS}}) { + if ($what) { + next if ($l->{IS_DEFERRED} and $what == PRIMITIVES); + next if (not $l->{IS_DEFERRED} and $what == DEFERRED); + } if ($l->{TYPE} eq "ARRAY") { pidl "uint32 i_$e->{NAME}_$l->{LEVEL_INDEX};"; $output = 1; @@ -42,11 +50,11 @@ sub DeclareArrayVariables($) pidl "" if $output; } -sub ParseElementLevelData($$$$$) +sub ParseElementLevelData($$$$$$) { - my ($e,$l,$nl,$env,$varname) = @_; + my ($e,$l,$nl,$env,$varname,$what) = @_; - my @args = ($e,$l,$varname); + my @args = ($e,$l,$varname,$what); # See if we need to add a level argument because we're parsing a union foreach (@{$e->{LEVELS}}) { @@ -54,64 +62,107 @@ sub ParseElementLevelData($$$$$) if ($_->{TYPE} eq "SWITCH"); } - pidl "if (!".DissectType(@args).")"; + my $c = DissectType(@args); + return if not $c; + + pidl "if (!$c)"; pidl "\treturn False;"; } -sub ParseElementLevelArray($$$$$) +sub ParseElementLevelArray($$$$$$) { - my ($e,$l,$nl,$env,$varname) = @_; + my ($e,$l,$nl,$env,$varname,$what) = @_; my $len = ParseExpr($l->{LENGTH_IS}, $env); + my $size = ParseExpr($l->{SIZE_IS}, $env); + + if ($what == PRIMITIVES) { + # Fetch headers + if ($l->{IS_CONFORMANT} and not $l->{IS_SURROUNDING}) { + pidl "if (!prs_uint32(\"size_$e->{NAME}\", ps, depth, &" . ParseExpr("size_$e->{NAME}", $env) . "))"; + pidl "\treturn False;"; + pidl ""; + } + + if ($l->{IS_VARYING}) { + pidl "if (!prs_uint32(\"offset_$e->{NAME}\", ps, depth, &" . ParseExpr("offset_$e->{NAME}", $env) . "))"; + pidl "\treturn False;"; + pidl ""; + + pidl "if (!prs_uint32(\"length_$e->{NAME}\", ps, depth, &" . ParseExpr("length_$e->{NAME}", $env) . "))"; + pidl "\treturn False;"; + pidl ""; + } + } + + # Everything but fixed arrays have to be allocated + if (!$l->{IS_FIXED} and $what == PRIMITIVES) { + pidl "if (UNMARSHALLING(ps)) {"; + indent; + pidl "$varname = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*$varname)*$size);"; + deindent; + pidl "}"; + } + + return if ($what == DEFERRED and not ContainsDeferred($e,$l)); my $i = "i_$e->{NAME}_$l->{LEVEL_INDEX}"; pidl "for ($i=0; $i<$len;$i++) {"; indent; - ParseElementLevel($e,$nl,$env,$varname."[$i]"); + ParseElementLevel($e,$nl,$env,$varname."[$i]",$what); deindent; pidl "}"; } -sub ParseElementLevelSwitch($$$$$) +sub ParseElementLevelSwitch($$$$$$) { - my ($e,$l,$nl,$env,$varname) = @_; + my ($e,$l,$nl,$env,$varname,$what) = @_; - pidl "if (!prs_uint32(\"level\", ps, depth, &" . ParseExpr("level_$e->{NAME}", $env) . "))"; - pidl "\treturn False;"; - pidl ""; + if ($what == PRIMITIVES) { + pidl "if (!prs_uint32(\"level\", ps, depth, &" . ParseExpr("level_$e->{NAME}", $env) . "))"; + pidl "\treturn False;"; + pidl ""; + } - ParseElementLevel($e,$nl,$env,$varname); + ParseElementLevel($e,$nl,$env,$varname,$what); } -sub ParseElementLevelPtr($$$$$) +sub ParseElementLevelPtr($$$$$$) { - my ($e,$l,$nl,$env,$varname) = @_; + my ($e,$l,$nl,$env,$varname,$what) = @_; + + if ($what == PRIMITIVES) { + pidl "if (!prs_uint32(\"ptr_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr_$e->{NAME}", $env) . "))"; + pidl "\treturn False;"; + pidl ""; + } if ($l->{POINTER_TYPE} eq "relative") { fatal($e, "relative pointers not supported for Samba 3"); + #FIXME } - - pidl "if (!prs_uint32(\"ptr_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr_$e->{NAME}", $env) . "))"; - pidl "\treturn False;"; - pidl ""; - pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {"; - indent; - ParseElementLevel($e,$nl,$env,$varname); - deindent; - pidl "}"; + if ($what == DEFERRED) { + pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {"; + indent; + ParseElementLevel($e,$nl,$env,$varname,PRIMITIVES); + ParseElementLevel($e,$nl,$env,$varname,DEFERRED); + deindent; + pidl "}"; + } } -sub ParseElementLevelSubcontext($$$$$) +sub ParseElementLevelSubcontext($$$$$$) { - my ($e,$l,$nl,$env,$varname) = @_; + my ($e,$l,$nl,$env,$varname,$what) = @_; fatal($e, "subcontext() not supported for Samba 3"); + #FIXME } -sub ParseElementLevel($$$$) +sub ParseElementLevel($$$$$) { - my ($e,$l,$env,$varname) = @_; + my ($e,$l,$env,$varname,$what) = @_; { DATA => \&ParseElementLevelData, @@ -119,14 +170,14 @@ sub ParseElementLevel($$$$) POINTER => \&ParseElementLevelPtr, SWITCH => \&ParseElementLevelSwitch, ARRAY => \&ParseElementLevelArray - }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname); + }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname,$what); } -sub ParseElement($$) +sub ParseElement($$$) { - my ($e,$env) = @_; + my ($e,$env,$what) = @_; - ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env)); + ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env), $what); } sub InitLevel($$$$) @@ -164,29 +215,35 @@ sub GenerateEnvElement($$) $env->{"level_$e->{NAME}"} = "v->level_$e->{NAME}"; } elsif ($l->{TYPE} eq "ARRAY") { $env->{"length_$e->{NAME}"} = "v->length_$e->{NAME}"; + $env->{"size_$e->{NAME}"} = "v->size_$e->{NAME}"; + $env->{"offset_$e->{NAME}"} = "v->offset_$e->{NAME}"; } } } -sub CreateStruct($$$$$) +sub ParseStruct($$$) { - my ($fn,$ifn, $s,$es,$a) = @_; + my ($if,$s,$n) = @_; + + my $fn = "$if->{NAME}_io_$n"; + my $sn = uc("$if->{NAME}_$n"); + my $ifn = "init_$if->{NAME}_$n"; my $args = ""; - foreach (@$es) { + foreach (@{$s->{ELEMENTS}}) { $args .= ", " . DeclLong($_); } my $env = { "this" => "v" }; - GenerateEnvElement($_, $env) foreach (@$es); + GenerateEnvElement($_, $env) foreach (@{$s->{ELEMENTS}}); - pidl "BOOL $ifn($s *v$args)"; + pidl "BOOL $ifn($sn *v$args)"; pidl "{"; indent; pidl "DEBUG(5,(\"$ifn\\n\"));"; pidl ""; # Call init for all arguments - foreach (@$es) { + foreach (@{$s->{ELEMENTS}}) { InitLevel($_, $_->{LEVELS}[0], $_->{NAME}, $env); pidl ""; } @@ -194,24 +251,31 @@ sub CreateStruct($$$$$) deindent; pidl "}"; pidl ""; + + my $pfn = "$fn\_p"; + my $dfn = "$fn\_d"; - pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)"; + pidl "BOOL $pfn(const char *desc, $sn *v, prs_struct *ps, int depth)"; pidl "{"; indent; - DeclareArrayVariables($es); + DeclareArrayVariables($s->{ELEMENTS}, PRIMITIVES); pidl "if (v == NULL)"; pidl "\treturn False;"; pidl ""; - pidl "prs_debug(ps, depth, desc, \"$fn\");"; + pidl "prs_debug(ps, depth, desc, \"$pfn\");"; pidl "depth++;"; - if ($a > 0) { - pidl "if (!prs_align_custom(ps, $a))"; + pidl "if (!prs_align_custom(ps, $s->{ALIGN}))"; + pidl "\treturn False;"; + pidl ""; + + if ($s->{SURROUNDING_ELEMENT}) { + pidl "if (!prs_uint32(\"size_$s->{SURROUNDING_ELEMENT}->{NAME}\", ps, depth, &" . ParseExpr("size_$s->{SURROUNDING_ELEMENT}->{NAME}", $env) . "))"; pidl "\treturn False;"; pidl ""; } - foreach (@$es) { - ParseElement($_, $env); + foreach (@{$s->{ELEMENTS}}) { + ParseElement($_, $env, PRIMITIVES); pidl ""; } @@ -219,16 +283,29 @@ sub CreateStruct($$$$$) deindent; pidl "}"; pidl ""; -} -sub ParseStruct($$$) -{ - my ($if,$s,$n) = @_; + pidl "BOOL $dfn(const char *desc, $sn *v, prs_struct *ps, int depth)"; + pidl "{"; + indent; + DeclareArrayVariables($s->{ELEMENTS}, DEFERRED); + pidl "if (v == NULL)"; + pidl "\treturn False;"; + pidl ""; + pidl "prs_debug(ps, depth, desc, \"$dfn\");"; + pidl "depth++;"; + pidl "if (!prs_align_custom(ps, $s->{ALIGN}))"; + pidl "\treturn False;"; + pidl ""; - my $fn = "$if->{NAME}_io_$n"; - my $sn = uc("$if->{NAME}_$n"); + foreach (@{$s->{ELEMENTS}}) { + ParseElement($_, $env, DEFERRED); + pidl ""; + } - CreateStruct($fn, "init_$if->{NAME}_$n", $sn, $s->{ELEMENTS}, $s->{ALIGN}); + pidl "return True;"; + deindent; + pidl "}"; + pidl ""; } sub ParseUnion($$$) @@ -238,7 +315,44 @@ sub ParseUnion($$$) my $fn = "$if->{NAME}_io_$n"; my $sn = uc("$if->{NAME}_$n"); - pidl "BOOL $fn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)"; + my $pfn = "$fn\_p"; + my $dfn = "$fn\_d"; + + pidl "BOOL $pfn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)"; + pidl "{"; + indent; + DeclareArrayVariables($u->{ELEMENTS}); + pidl "if (!prs_align_custom(ps, $u->{ALIGN}))"; + pidl "\treturn False;"; + pidl ""; + + pidl "switch (level) {"; + indent; + + foreach (@{$u->{ELEMENTS}}) { + pidl "$_->{CASE}:"; + indent; + if ($_->{TYPE} ne "EMPTY") { + pidl "depth++;"; + my $env = {}; + GenerateEnvElement($_, $env); + ParseElement($_, $env, PRIMITIVES); + ParseElement($_, $env, DEFERRED); + pidl "depth--;"; + } + pidl "break;"; + deindent; + pidl ""; + } + + deindent; + pidl "}"; + pidl ""; + pidl "return True;"; + deindent; + pidl "}"; + + pidl "BOOL $dfn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)"; pidl "{"; indent; DeclareArrayVariables($u->{ELEMENTS}); @@ -256,7 +370,7 @@ sub ParseUnion($$$) pidl "depth++;"; my $env = {}; GenerateEnvElement($_, $env); - ParseElement($_, $env); + ParseElement($_, $env, DEFERRED); pidl "depth--;"; } pidl "break;"; @@ -270,6 +384,56 @@ sub ParseUnion($$$) pidl "return True;"; deindent; pidl "}"; + +} + +sub CreateFnDirection($$$$) +{ + my ($fn,$ifn, $s,$es) = @_; + + my $args = ""; + foreach (@$es) { + $args .= ", " . DeclLong($_); + } + + my $env = { "this" => "v" }; + GenerateEnvElement($_, $env) foreach (@$es); + + pidl "BOOL $ifn($s *v$args)"; + pidl "{"; + indent; + pidl "DEBUG(5,(\"$ifn\\n\"));"; + pidl ""; + # Call init for all arguments + foreach (@$es) { + InitLevel($_, $_->{LEVELS}[0], $_->{NAME}, $env); + pidl ""; + } + pidl "return True;"; + deindent; + pidl "}"; + pidl ""; + + pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)"; + pidl "{"; + indent; + DeclareArrayVariables($es); + pidl "if (v == NULL)"; + pidl "\treturn False;"; + pidl ""; + pidl "prs_debug(ps, depth, desc, \"$fn\");"; + pidl "depth++;"; + + foreach (@$es) { + ParseElement($_, $env, PRIMITIVES); + ParseElement($_, $env, DEFERRED); + pidl ""; + } + + pidl "return True;"; + deindent; + pidl "}"; + pidl ""; } sub ParseFunction($$) @@ -297,14 +461,14 @@ sub ParseFunction($$) } ); } - CreateStruct("$if->{NAME}_io_q_$fn->{NAME}", + CreateFnDirection("$if->{NAME}_io_q_$fn->{NAME}", "init_$if->{NAME}_q_$fn->{NAME}", uc("$if->{NAME}_q_$fn->{NAME}"), - \@in, 0); - CreateStruct("$if->{NAME}_io_r_$fn->{NAME}", + \@in); + CreateFnDirection("$if->{NAME}_io_r_$fn->{NAME}", "init_$if->{NAME}_r_$fn->{NAME}", uc("$if->{NAME}_r_$fn->{NAME}"), - \@out, 0); + \@out); } sub ParseInterface($) diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm index a3bf91d54f..9a7a31a6bb 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Types.pm @@ -109,50 +109,50 @@ my $known_types = { DECL => "uint8", INIT => \&init_scalar, - DISSECT => \&dissect_scalar, + DISSECT_P => \&dissect_scalar, }, uint16 => { DECL => "uint16", INIT => \&init_scalar, - DISSECT => \&dissect_scalar, + DISSECT_P => \&dissect_scalar, }, uint32 => { DECL => "uint32", INIT => \&init_scalar, - DISSECT => \&dissect_scalar, + DISSECT_P => \&dissect_scalar, }, uint64 => { DECL => "uint64", INIT => \&init_scalar, - DISSECT => \&dissect_scalar, + DISSECT_P => \&dissect_scalar, }, string => { DECL => \&decl_string, EXT_DECL => \&ext_decl_string, INIT => \&init_string, - DISSECT => \&dissect_string, + DISSECT_P => \&dissect_string, }, NTSTATUS => { DECL => "NTSTATUS", INIT => \&init_scalar, - DISSECT => \&dissect_scalar, + DISSECT_P => \&dissect_scalar, }, WERROR => { DECL => "WERROR", INIT => \&init_scalar, - DISSECT => \&dissect_scalar, + DISSECT_P => \&dissect_scalar, }, GUID => { DECL => "struct uuid", INIT => "", - DISSECT => sub { + DISSECT_P => sub { my ($e,$l,$n) = @_; return "smb_io_uuid(\"$e->{NAME}\", &$n, ps, depth)"; } @@ -161,7 +161,7 @@ my $known_types = { DECL => "NTTIME", INIT => "", - DISSECT => sub { + DISSECT_P => sub { my ($e,$l,$n) = @_; return "smb_io_nttime(\"$e->{NAME}\", &n, ps, depth)"; } @@ -170,7 +170,7 @@ my $known_types = { DECL => "DOM_SID", INIT => "", - DISSECT => sub { + DISSECT_P => sub { my ($e,$l,$n) = @_; return "smb_io_dom_sid(\"$e->{NAME}\", &n, ps, depth)"; } @@ -179,7 +179,7 @@ my $known_types = { DECL => "POLICY_HND", INIT => "", - DISSECT => sub { + DISSECT_P => sub { my ($e,$l,$n) = @_; return "smb_io_pol_hnd(\"$e->{NAME}\", &n, ps, depth)"; } @@ -301,6 +301,7 @@ sub DissectType my $e = shift @_; my $l = shift @_; my $varname = shift @_; + my $what = shift @_; my $t = $known_types->{$l->{DATA_TYPE}}; @@ -309,11 +310,20 @@ sub DissectType return undef; } + my $dissect; + if ($what == 1) { #primitives + $dissect = $t->{DISSECT_P}; + } elsif ($what == 2) { + $dissect = $t->{DISSECT_D}; + } + + return "" if not defined($dissect); + # DISSECT can be a function - if (ref($t->{DISSECT}) eq "CODE") { - return $t->{DISSECT}->(@args); + if (ref($dissect) eq "CODE") { + return $dissect->(@args); } else { - return $t->{DISSECT}; + return $dissect; } } @@ -330,25 +340,40 @@ sub LoadTypes($) return "$n = $v;"; }; - my $dissect; + my $dissect_d; + my $dissect_p; if ($td->{DATA}->{TYPE} eq "UNION") { - $dissect = sub { - my ($e,$l,$n,$s) = @_; + $dissect_p = sub { + my ($e,$l,$n,$w,$s) = @_; + + return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, $s, ps, depth)"; + }; - return "$if->{NAME}_io_$td->{NAME}(\"$e->{NAME}\", &$n, $s, ps, depth)"; + $dissect_d = sub { + my ($e,$l,$n,$w,$s) = @_; + + return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, $s, ps, depth)"; }; + } else { - $dissect = sub { - my ($e,$l,$n) = @_; + $dissect_p = sub { + my ($e,$l,$n,$w) = @_; - return "$if->{NAME}_io_$td->{NAME}(\"$e->{NAME}\", &$n, ps, depth)"; + return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, ps, depth)"; }; + $dissect_d = sub { + my ($e,$l,$n,$w) = @_; + + return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, ps, depth)"; + }; + } AddType($td->{NAME}, { DECL => $decl, INIT => $init, - DISSECT => $dissect + DISSECT_D => $dissect_d, + DISSECT_P => $dissect_p }); } } -- cgit