lib/fuzzing: add fuzz_ndr_X
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Thu, 31 Oct 2019 03:28:28 +0000 (16:28 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 10 Dec 2019 07:50:28 +0000 (07:50 +0000)
This NDR fuzzer links with each "interface" in the IDL files to
create avsingle binary.  This tries to matches what the fuzzing
engines desire.

It started as a copy of ndrdump but very little of that remains
in place.

The fancy build rules try to avoid needing a lof of boilerplate
in the wscript_build files and ensure new fuzzers are generated
and run when new IDL is added automatically.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Pair-programmed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
buildtools/wafsamba/samba_pidl.py
buildtools/wafsamba/wscript
lib/fuzzing/fuzz_ndr_X.c [new file with mode: 0644]
lib/fuzzing/wscript_build
librpc/idl/wscript_build
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
wscript_build

index a34c871d18317643fdae5e090d3c5d5a57afb839..8785563e5e639c708edf9e39a1c3effe967e7462 100644 (file)
@@ -108,14 +108,22 @@ def SAMBA_PIDL(bld, pname, source,
     t.more_includes = '#' + bld.path.path_from(bld.srcnode)
 Build.BuildContext.SAMBA_PIDL = SAMBA_PIDL
 
-
 def SAMBA_PIDL_LIST(bld, name, source,
                     options='',
                     output_dir='.',
-                    generate_tables=True):
+                    generate_tables=True,
+                    generate_fuzzers=True):
     '''A wrapper for building a set of IDL files'''
     for p in TO_LIST(source):
         bld.SAMBA_PIDL(name, p, options=options, output_dir=output_dir, generate_tables=generate_tables)
+
+        # Some IDL files don't exactly match between name and
+        # "interface" so we need a way to skip those, while other IDL
+        # files have the table generation skipped entirely, on which
+        # the fuzzers rely
+        if generate_tables and generate_fuzzers:
+            interface = p[0:-4] # strip off the .idl suffix
+            bld.SAMBA_NDR_FUZZ(interface)
 Build.BuildContext.SAMBA_PIDL_LIST = SAMBA_PIDL_LIST
 
 
index b9f2f4956177be0d6a670135df4176b361ce0eee..764e357cc873bb2b0a749008d102061df9a42d13 100644 (file)
@@ -605,7 +605,7 @@ struct foo bar = { .y = 'X', .x = 1 };
 
     conf.env.enable_libfuzzer = Options.options.enable_libfuzzer
     if conf.env.enable_libfuzzer:
-        conf.DEFINE('ENABLE_LIBFUZZER', 1)
+        conf.DEFINE('FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION', 1)
         conf.env.FUZZ_TARGET_LDFLAGS = Options.options.FUZZ_TARGET_LDFLAGS
 
     conf.load('clang_compilation_database')
diff --git a/lib/fuzzing/fuzz_ndr_X.c b/lib/fuzzing/fuzz_ndr_X.c
new file mode 100644 (file)
index 0000000..8c9e572
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+   Unix SMB/CIFS implementation.
+   SMB torture tester
+   Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Jelmer Vernooij 2006
+   Copyright (C) Andrew Bartlett 2019
+   Copyright (C) Catalyst.NET Ltd 2019
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "system/locale.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "util/byteorder.h"
+#include "fuzzing/fuzzing.h"
+
+extern const struct ndr_interface_table FUZZ_PIPE_TABLE;
+
+#define FLAG_NDR64 4
+
+enum {
+       TYPE_STRUCT = 0,
+       TYPE_IN,
+       TYPE_OUT
+};
+
+/*
+ * header design (little endian):
+ *
+ * struct {
+ *   uint16_t flags;
+ *   uint16_t function_or_struct_no;
+ * };
+ */
+
+/*
+ * We want an even number here to ensure 4-byte alignment later
+ * not just for efficieny but because the fuzzers are known to guess
+ * that numbers will be 4-byte aligned
+ */
+#define HEADER_SIZE 4
+
+#define INVALID_FLAGS (~(FLAG_NDR64 | 3))
+
+static const struct ndr_interface_call *find_function(
+       const struct ndr_interface_table *p,
+       unsigned int function_no)
+{
+       if (function_no >= p->num_calls) {
+               return NULL;
+       }
+       return &p->calls[function_no];
+}
+
+/*
+ * Get a public structure by number and return it as if it were
+ * a function.
+ */
+static const struct ndr_interface_call *find_struct(
+       const struct ndr_interface_table *p,
+       unsigned int struct_no,
+       struct ndr_interface_call *out_buffer)
+{
+       const struct ndr_interface_public_struct *s = NULL;
+
+       if (struct_no >= p->num_public_structs) {
+               return NULL;
+       }
+
+       s = &p->public_structs[struct_no];
+
+       *out_buffer = (struct ndr_interface_call) {
+               .name = s->name,
+               .struct_size = s->struct_size,
+               .ndr_pull = s->ndr_pull,
+               .ndr_push = s->ndr_push,
+               .ndr_print = s->ndr_print
+       };
+       return out_buffer;
+}
+
+
+static NTSTATUS pull_chunks(struct ndr_pull *ndr_pull,
+                           const struct ndr_interface_call_pipes *pipes)
+{
+       enum ndr_err_code ndr_err;
+       uint32_t i;
+
+       for (i=0; i < pipes->num_pipes; i++) {
+               while (true) {
+                       void *saved_mem_ctx;
+                       uint32_t *count;
+                       void *c;
+
+                       c = talloc_zero_size(ndr_pull, pipes->pipes[i].chunk_struct_size);
+                       if (c == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       /*
+                        * Note: the first struct member is always
+                        * 'uint32_t count;'
+                        */
+                       count = (uint32_t *)c;
+
+                       saved_mem_ctx = ndr_pull->current_mem_ctx;
+                       ndr_pull->current_mem_ctx = c;
+                       ndr_err = pipes->pipes[i].ndr_pull(ndr_pull, NDR_SCALARS, c);
+                       ndr_pull->current_mem_ctx = saved_mem_ctx;
+
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               talloc_free(c);
+                               return ndr_map_error2ntstatus(ndr_err);
+                       }
+                       if (*count == 0) {
+                               talloc_free(c);
+                               break;
+                       }
+                       talloc_free(c);
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
+static void ndr_print_nothing(struct ndr_print *ndr, const char *format, ...)
+{
+       /*
+        * This is here so that we walk the tree but don't output anything.
+        * This helps find buggy ndr_print routines
+        */
+
+       /*
+        * TODO: consider calling snprinf() to find strings without NULL
+        * terminators (for example)
+        */
+}
+
+
+int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+       uint8_t type;
+       int pull_push_print_flags;
+       uint16_t fuzz_packet_flags, function;
+       TALLOC_CTX *mem_ctx = NULL;
+       uint32_t ndr_flags = 0;
+       struct ndr_push *ndr_push;
+       enum ndr_err_code ndr_err;
+       struct ndr_interface_call f_buffer;
+       const struct ndr_interface_call *f = NULL;
+       NTSTATUS status;
+
+       if (size < HEADER_SIZE) {
+               /*
+                * the first few bytes decide what is being fuzzed --
+                * if they aren't all there we do nothing.
+                */
+               return 0;
+       }
+
+       fuzz_packet_flags = SVAL(data, 0);
+       if (fuzz_packet_flags & INVALID_FLAGS) {
+               return 0;
+       }
+
+       function = SVAL(data, 2);
+
+       type = fuzz_packet_flags & 3;
+
+       switch (type) {
+       case TYPE_STRUCT:
+               pull_push_print_flags = NDR_SCALARS|NDR_BUFFERS;
+               f = find_struct(&FUZZ_PIPE_TABLE, function, &f_buffer);
+               break;
+       case TYPE_IN:
+               pull_push_print_flags = NDR_IN;
+               f = find_function(&FUZZ_PIPE_TABLE, function);
+               break;
+       case TYPE_OUT:
+               pull_push_print_flags = NDR_OUT;
+               f = find_function(&FUZZ_PIPE_TABLE, function);
+               break;
+       default:
+               return 0;
+       }
+
+       if (f == NULL) {
+               return 0;
+       }
+       if (fuzz_packet_flags & FLAG_NDR64) {
+               ndr_flags |= LIBNDR_FLAG_NDR64;
+       }
+
+       mem_ctx = talloc_init("ndrfuzz");
+
+       {
+               /*
+                * f->struct_size is well-controlled, it is essentially
+                * defined in the IDL
+                */
+               uint8_t st[f->struct_size];
+
+               DATA_BLOB blob = data_blob_const(data + HEADER_SIZE,
+                                                size - HEADER_SIZE);
+               struct ndr_pull *ndr_pull = ndr_pull_init_blob(&blob,
+                                                              mem_ctx);
+
+               if (ndr_pull == NULL) {
+                       perror("ndr_pull_init_blob");
+                       TALLOC_FREE(mem_ctx);
+                       return 0;
+               }
+               ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+
+               if (type == TYPE_OUT) {
+                       status = pull_chunks(ndr_pull,
+                                            &f->out_pipes);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(mem_ctx);
+                               return 0;
+                       }
+               }
+
+               ndr_err = f->ndr_pull(ndr_pull,
+                                     pull_push_print_flags,
+                                     st);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       TALLOC_FREE(mem_ctx);
+                       return 0;
+               }
+
+               if (type == TYPE_IN) {
+                       status = pull_chunks(ndr_pull,
+                                            &f->in_pipes);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(mem_ctx);
+                               return 0;
+                       }
+               }
+
+               ndr_push = ndr_push_init_ctx(mem_ctx);
+               if (ndr_push == NULL) {
+                       TALLOC_FREE(mem_ctx);
+                       return 0;
+               }
+
+               ndr_push->flags |= ndr_flags;
+
+               /*
+                * Now push what was pulled, just in case we generated an
+                * invalid structure in memory, this should notice
+                */
+               ndr_err = f->ndr_push(ndr_push,
+                                     pull_push_print_flags,
+                                     st);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       TALLOC_FREE(mem_ctx);
+                       return 0;
+               }
+
+               {
+                       struct ndr_print *ndr_print = talloc_zero(mem_ctx, struct ndr_print);
+                       ndr_print->print = ndr_print_nothing;
+                       ndr_print->depth = 1;
+
+                       /*
+                        * Finally print (to nowhere) the structure, this may also
+                        * notice invalid memory
+                        */
+                       f->ndr_print(ndr_print,
+                                    f->name,
+                                    pull_push_print_flags,
+                                    st);
+               }
+       }
+       TALLOC_FREE(mem_ctx);
+
+       return 0;
+}
index 386145c43b2e51072b4536159d80dd81fe142acb..25cdcd323bf9b372f54280ab0979c926ebb67244 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/env python
 
+from waflib import Build
+
 bld.SAMBA_SUBSYSTEM('fuzzing',
     source='fuzzing.c',
     deps='talloc',
@@ -40,3 +42,81 @@ bld.SAMBA_BINARY('fuzz_ldb_parse_tree',
                  source='fuzz_ldb_parse_tree.c',
                  deps='fuzzing ldb',
                  fuzzer=True)
+
+def SAMBA_NDR_FUZZ(bld, interface):
+    name = "fuzz_ndr_%s" % (interface.lower())
+    fuzz_dir = os.path.join(bld.env.srcdir, 'lib/fuzzing')
+    fuzz_reldir = os.path.relpath(fuzz_dir, bld.path.abspath())
+    fuzz_src = os.path.join(fuzz_reldir, 'fuzz_ndr_X.c')
+    fuzz_named_src = os.path.join(fuzz_reldir,
+                                  'fuzz_ndr_%s.c' % interface.lower())
+
+    # Work around an issue that WAF is invoked from up to 3 different
+    # directories so doesn't create a unique name for the multiple .o
+    # files like it would if called from just one place.
+    bld.SAMBA_GENERATOR(fuzz_named_src,
+                        source=fuzz_src,
+                        target=fuzz_named_src,
+                        rule='cp ${SRC} ${TGT}')
+
+    bld.SAMBA_BINARY(name, source=fuzz_named_src,
+                     cflags = "-D FUZZ_PIPE_TABLE=ndr_table_%s" % interface,
+                     deps = "ndr-table NDR_DCERPC",
+                     install=False,
+                     fuzzer=True)
+
+Build.BuildContext.SAMBA_NDR_FUZZ = SAMBA_NDR_FUZZ
+
+# fuzz_ndr_X is generated from the list if IDL fed to PIDL
+# however there are exceptions to the normal pattern
+bld.SAMBA_NDR_FUZZ('IOXIDResolver') # oxidresolver.idl
+bld.SAMBA_NDR_FUZZ('IRemoteActivation') # remact.idl
+bld.SAMBA_NDR_FUZZ('iremotewinspool') # winspool.idl
+bld.SAMBA_NDR_FUZZ('FileServerVssAgent') # fsvrp.idl
+bld.SAMBA_NDR_FUZZ('lsarpc') # lsa.idl
+bld.SAMBA_NDR_FUZZ('netdfs') # dfs.idl
+bld.SAMBA_NDR_FUZZ('nfs4acl_interface') # nfs4acl.idl
+bld.SAMBA_NDR_FUZZ('ObjectRpcBaseTypes') # orpc.idl
+bld.SAMBA_NDR_FUZZ('rpcecho') # echo.idl
+
+# quota.idl
+bld.SAMBA_NDR_FUZZ('file_quota')
+bld.SAMBA_NDR_FUZZ('smb2_query_quota')
+bld.SAMBA_NDR_FUZZ('smb1_nt_transact_query_quota')
+
+# ioctl.idl
+bld.SAMBA_NDR_FUZZ('copychunk')
+bld.SAMBA_NDR_FUZZ('compression')
+bld.SAMBA_NDR_FUZZ('netinterface')
+bld.SAMBA_NDR_FUZZ('sparse')
+bld.SAMBA_NDR_FUZZ('resiliency')
+bld.SAMBA_NDR_FUZZ('trim')
+
+# Skipped: dsbackup (all todo)
+
+# WMI tables
+bld.SAMBA_NDR_FUZZ('IWbemClassObject')
+bld.SAMBA_NDR_FUZZ('IWbemServices')
+bld.SAMBA_NDR_FUZZ('IEnumWbemClassObject')
+bld.SAMBA_NDR_FUZZ('IWbemContext')
+bld.SAMBA_NDR_FUZZ('IWbemLevel1Login')
+bld.SAMBA_NDR_FUZZ('IWbemWCOSmartEnum')
+bld.SAMBA_NDR_FUZZ('IWbemFetchSmartEnum')
+bld.SAMBA_NDR_FUZZ('IWbemCallResult')
+bld.SAMBA_NDR_FUZZ('IWbemObjectSink')
+
+# DCOM tables
+bld.SAMBA_NDR_FUZZ('dcom_Unknown')
+bld.SAMBA_NDR_FUZZ('IUnknown')
+bld.SAMBA_NDR_FUZZ('IClassFactory')
+bld.SAMBA_NDR_FUZZ('IRemUnknown')
+bld.SAMBA_NDR_FUZZ('IClassActivator')
+bld.SAMBA_NDR_FUZZ('ISCMLocalActivator')
+bld.SAMBA_NDR_FUZZ('IMachineLocalActivator')
+bld.SAMBA_NDR_FUZZ('ILocalObjectExporter')
+bld.SAMBA_NDR_FUZZ('ISystemActivator')
+bld.SAMBA_NDR_FUZZ('IRemUnknown2')
+bld.SAMBA_NDR_FUZZ('IDispatch')
+bld.SAMBA_NDR_FUZZ('IMarshal')
+bld.SAMBA_NDR_FUZZ('ICoffeeMachine')
+bld.SAMBA_NDR_FUZZ('IStream')
index c9b19c4aac4dfe7efccd07ec39887509c2dc1347..5dda944ca7165864af518c2f8f130551f9180f84 100644 (file)
@@ -5,16 +5,26 @@ bld.SAMBA_PIDL_LIST('PIDL',
                        eventlog.idl
                        browser.idl dssetup.idl frsapi.idl
                        spoolss.idl
-                       dnsserver.idl echo.idl lsa.idl
+                       dnsserver.idl
                        samr.idl srvsvc.idl winreg.idl
                        mgmt.idl netlogon.idl
                        svcctl.idl wkssvc.idl eventlog6.idl backupkey.idl
-                       fsrvp.idl witness.idl clusapi.idl
-                       mdssvc.idl
-                       winspool.idl''',
+                       witness.idl clusapi.idl
+                       mdssvc.idl''',
                     options='--header --ndr-parser --samba3-ndr-server --server --client --python',
                     output_dir='../gen_ndr')
 
+# The interface names here are not the same as the IDL name, so the
+# auto-genration of the fuzzer fails to link
+bld.SAMBA_PIDL_LIST('PIDL',
+                    '''echo.idl
+                       fsrvp.idl
+                       lsa.idl
+                       winspool.idl''',
+                    options='--header --ndr-parser --samba3-ndr-server --server --client --python',
+                    output_dir='../gen_ndr',
+                    generate_fuzzers=False)
+
 # Services that we only have a client for
 bld.SAMBA_PIDL_LIST('PIDL',
                     '''atsvc.idl''',
@@ -23,26 +33,42 @@ bld.SAMBA_PIDL_LIST('PIDL',
 
 # Services that we only have a server in the source3 style
 bld.SAMBA_PIDL_LIST('PIDL',
-                    '''dfs.idl initshutdown.idl ntsvcs.idl''',
+                    '''initshutdown.idl ntsvcs.idl''',
                     options='--header --ndr-parser --client --python --samba3-ndr-server',
                     output_dir='../gen_ndr')
 
-# Services that we only have a server in the source4 style
+# The interface names here are not the same as the IDL name, so the
+# auto-genration of the fuzzer fails to link
+bld.SAMBA_PIDL_LIST('PIDL',
+                    '''dfs.idl''',
+                    options='--header --ndr-parser --client --python --samba3-ndr-server',
+                    output_dir='../gen_ndr',
+                    generate_fuzzers=False)
+
+# Services that we only have a server in the source4 style. 
+
 bld.SAMBA_PIDL_LIST('PIDL',
                     '''unixinfo.idl''',
                     options='--header --ndr-parser --client --python --server',
                     output_dir='../gen_ndr')
 
 # DCOM stuff
+
+# The interface names here are not the same as the IDL name, so the
+# auto-genration of the fuzzer fails to link
 bld.SAMBA_PIDL_LIST('PIDL',
                     '''oxidresolver.idl remact.idl''',
                     options='--header --ndr-parser --client',
-                    output_dir='../gen_ndr')
+                    output_dir='../gen_ndr',
+                    generate_fuzzers=False)
 
+# The interface names here are not the same as the IDL name, so the
+# auto-genration of the fuzzer fails to link
 bld.SAMBA_PIDL_LIST('PIDL',
                     'wmi.idl dcom.idl',
                     options='--header --ndr-parser --server --client --dcom-proxy --com-header',
-                    output_dir='../gen_ndr')
+                    output_dir='../gen_ndr',
+                    generate_fuzzers=False)
 
 # DCE/RPC protocols which Samba does not implement a client or server
 # for
@@ -50,13 +76,11 @@ bld.SAMBA_PIDL_LIST('PIDL',
 bld.SAMBA_PIDL_LIST('PIDL',
                     '''
                     audiosrv.idl
-                    dsbackup.idl
                     efs.idl
                     frstrans.idl
                     frsrpc.idl
                     keysvc.idl
                     msgsvc.idl
-                    orpc.idl
                     policyagent.idl
                     rot.idl
                     scerpc.idl
@@ -67,6 +91,18 @@ bld.SAMBA_PIDL_LIST('PIDL',
                     options='--header --ndr-parser',
                     output_dir='../gen_ndr')
 
+# The interface names here are not the same as the IDL name, so the
+# auto-genration of the fuzzer fails to link
+
+bld.SAMBA_PIDL_LIST('PIDL',
+                    '''
+                    dsbackup.idl
+                    orpc.idl
+                    ''',
+                    options='--header --ndr-parser',
+                    output_dir='../gen_ndr',
+                    generate_fuzzers=False)
+
 # Non-DCE/RPC protocols encoded in IDL for Samba or helper IDLs for
 # DCE/RPC protocols (eg defining constands or structures but not
 # functions)
@@ -78,14 +114,11 @@ bld.SAMBA_PIDL_LIST('PIDL',
                     file_id.idl
                     fscc.idl
                     fsrvp_state.idl
-                    ioctl.idl
                     named_pipe_auth.idl
                     negoex.idl
-                    nfs4acl.idl
                     notify.idl
                     ntprinting.idl
                     printcap.idl
-                    quota.idl
                     rap.idl
                     schannel.idl
                     smb2_lease_struct.idl
@@ -93,6 +126,19 @@ bld.SAMBA_PIDL_LIST('PIDL',
                     options='--header --ndr-parser',
                     output_dir='../gen_ndr')
 
+# The interface names here are not the same as the IDL name, so the
+# auto-genration of the fuzzer fails to link
+
+bld.SAMBA_PIDL_LIST('PIDL',
+                    '''
+                    ioctl.idl
+                    nfs4acl.idl
+                    quota.idl
+                    ''',
+                    options='--header --ndr-parser',
+                    output_dir='../gen_ndr',
+                    generate_fuzzers=False)
+
 # Non-DCE/RPC protocls with Python bindings
 # (for structures or constants)
 
index 94428ec2037325bb8e38f146db632c8661a8ee69..91b5f9429949e6fefe354f17dfe847039dfa2f14 100644 (file)
@@ -2604,6 +2604,31 @@ sub ParseFunctionPull($$)
        $self->pidl("if (flags & NDR_OUT) {");
        $self->indent;
 
+       $self->pidl("#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION");
+
+       # This for fuzzers of ndr_pull where the out elements refer to
+       # in elements in size_is or length_is.
+       #
+       # Not actually very harmful but also not useful outsie a fuzzer
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               next unless (grep(/in/, @{$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"));
+               next if ($e->{LEVELS}[1]->{TYPE} eq "PIPE");
+               next if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY");
+
+               $self->pidl("if (r->in.$e->{NAME} == NULL) {");
+               $self->indent;
+               $self->pidl("NDR_PULL_ALLOC($ndr, r->in.$e->{NAME});");
+               $self->pidl("NDR_ZERO_STRUCTP(r->in.$e->{NAME});");
+               $self->deindent;
+               $self->pidl("}");
+       }
+
+       $self->pidl("#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */");
+
        $env = GenerateFunctionOutEnv($fn);
        foreach my $e (@{$fn->{ELEMENTS}}) {
                next unless grep(/out/, @{$e->{DIRECTION}});
index f9e033c0dab8cbc8e7356e3f93f47fc3ebbd34d8..b2e32987acb799524b406116a31118c1722842fd 100644 (file)
@@ -38,6 +38,11 @@ bld.CONFIGURE_FILE('docs-xml/build/DTD/samba.build.version',
                    DOC_VERSION=bld.env.DOC_VERSION)
 bld.RECURSE('docs-xml')
 
+# This needs to be earlier than anything containing IDL
+# That in turn allows the build rules for fuzz_ndr_X to be
+# near the code
+bld.RECURSE('lib/fuzzing')
+
 bld.RECURSE('lib/replace')
 bld.RECURSE('lib/socket')
 bld.RECURSE('lib/talloc')
@@ -150,7 +155,6 @@ bld.RECURSE('dfs_server')
 bld.RECURSE('file_server')
 bld.RECURSE('lib/krb5_wrap')
 bld.RECURSE('packaging')
-bld.RECURSE('lib/fuzzing')
 
 bld.RECURSE('testsuite/headers')