// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// #include "postgres.h" #include "access/xlog.h" #include "access/xact.h" #include "common/username.h" #include "executor/spi.h" #include "jit/jit.h" #include "libpq/libpq.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "optimizer/optimizer.h" #include "parser/analyze.h" #include "parser/parser.h" #include "storage/proc.h" #include "tcop/tcopprot.h" #include "utils/datetime.h" #include "utils/memutils.h" #include "utils/portal.h" #include "utils/snapmgr.h" #include "utils/timeout.h" static void exec_simple_query(const char *query_string) { MemoryContext oldcontext; List *parsetree_list; ListCell *parsetree_item; bool use_implicit_block; StartTransactionCommand(); oldcontext = MemoryContextSwitchTo(MessageContext); parsetree_list = raw_parser(query_string, RAW_PARSE_TYPE_NAME); MemoryContextSwitchTo(oldcontext); use_implicit_block = (list_length(parsetree_list) > 1); foreach(parsetree_item, parsetree_list) { RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item); bool snapshot_set = false; MemoryContext per_parsetree_context = NULL; List *querytree_list, *plantree_list; if (use_implicit_block) BeginImplicitTransactionBlock(); if (analyze_requires_snapshot(parsetree)) { PushActiveSnapshot(GetTransactionSnapshot()); snapshot_set = true; } if (lnext(parsetree_list, parsetree_item) != NULL) { per_parsetree_context = AllocSetContextCreate(MessageContext, "per-parsetree message context", ALLOCSET_DEFAULT_SIZES); oldcontext = MemoryContextSwitchTo(per_parsetree_context); } else oldcontext = MemoryContextSwitchTo(MessageContext); querytree_list = pg_analyze_and_rewrite(parsetree, query_string, NULL, 0, NULL); plantree_list = pg_plan_queries(querytree_list, query_string, CURSOR_OPT_PARALLEL_OK, NULL); if (per_parsetree_context){ MemoryContextDelete(per_parsetree_context); } CommitTransactionCommand(); } } int LLVMFuzzerInitialize(int *argc, char ***argv) { FuzzerInitialize("query_db", argv); return 0; } /* ** Main entry point. The fuzzer invokes this function with each ** fuzzed input. */ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { char* query_string; sigjmp_buf local_sigjmp_buf; query_string = (char*) calloc( (size+1), sizeof(char) ); memcpy(query_string, data, size); if (!sigsetjmp(local_sigjmp_buf, 0)) { PG_exception_stack = &local_sigjmp_buf; error_context_stack = NULL; set_stack_base(); disable_all_timeouts(false); QueryCancelPending = false; pq_comm_reset(); EmitErrorReport(); AbortCurrentTransaction(); PortalErrorCleanup(); SPICleanup(); jit_reset_after_error(); MemoryContextSwitchTo(TopMemoryContext); FlushErrorState(); MemoryContextSwitchTo(MessageContext); MemoryContextResetAndDeleteChildren(MessageContext); InvalidateCatalogSnapshotConditionally(); SetCurrentStatementStartTimestamp(); exec_simple_query(query_string); } free(query_string); return 0; }