• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #include "postgres.h"
18 
19 #include "access/xlog.h"
20 #include "access/xact.h"
21 #include "common/username.h"
22 #include "executor/spi.h"
23 #include "jit/jit.h"
24 #include "libpq/libpq.h"
25 #include "libpq/pqsignal.h"
26 #include "miscadmin.h"
27 #include "optimizer/optimizer.h"
28 #include "parser/analyze.h"
29 #include "parser/parser.h"
30 #include "storage/proc.h"
31 #include "tcop/tcopprot.h"
32 #include "utils/datetime.h"
33 #include "utils/memutils.h"
34 #include "utils/portal.h"
35 #include "utils/snapmgr.h"
36 #include "utils/timeout.h"
37 
38 static void
exec_simple_query(const char * query_string)39 exec_simple_query(const char *query_string)
40 {
41   MemoryContext oldcontext;
42   List       *parsetree_list;
43   ListCell   *parsetree_item;
44   bool        use_implicit_block;
45 
46   StartTransactionCommand();
47   oldcontext = MemoryContextSwitchTo(MessageContext);
48 
49   parsetree_list = raw_parser(query_string, RAW_PARSE_TYPE_NAME);
50   MemoryContextSwitchTo(oldcontext);
51 
52   use_implicit_block = (list_length(parsetree_list) > 1);
53 
54   foreach(parsetree_item, parsetree_list)
55     {
56       RawStmt    *parsetree = lfirst_node(RawStmt, parsetree_item);
57       bool        snapshot_set = false;
58       MemoryContext per_parsetree_context = NULL;
59       List       *querytree_list,
60 	*plantree_list;
61 
62       if (use_implicit_block)
63 	BeginImplicitTransactionBlock();
64 
65       if (analyze_requires_snapshot(parsetree))
66 	{
67 	  PushActiveSnapshot(GetTransactionSnapshot());
68 	  snapshot_set = true;
69 	}
70 
71       if (lnext(parsetree_list, parsetree_item) != NULL)
72 	{
73 	  per_parsetree_context =
74 	    AllocSetContextCreate(MessageContext,
75 				  "per-parsetree message context",
76 				  ALLOCSET_DEFAULT_SIZES);
77 	  oldcontext = MemoryContextSwitchTo(per_parsetree_context);
78 	}
79       else
80 	oldcontext = MemoryContextSwitchTo(MessageContext);
81 
82       querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
83 					      NULL, 0, NULL);
84 
85       plantree_list = pg_plan_queries(querytree_list, query_string,
86 				      CURSOR_OPT_PARALLEL_OK, NULL);
87 
88       if (per_parsetree_context){
89 	MemoryContextDelete(per_parsetree_context);
90       }
91       CommitTransactionCommand();
92     }
93 }
94 
95 
LLVMFuzzerInitialize(int * argc,char *** argv)96 int LLVMFuzzerInitialize(int *argc, char ***argv) {
97 	FuzzerInitialize("query_db", argv);
98 	return 0;
99 }
100 
101 
102 /*
103 ** Main entry point.  The fuzzer invokes this function with each
104 ** fuzzed input.
105 */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)106 int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
107   char* query_string;
108   sigjmp_buf local_sigjmp_buf;
109 
110   query_string = (char*) calloc( (size+1), sizeof(char) );
111   memcpy(query_string, data, size);
112 
113   if (!sigsetjmp(local_sigjmp_buf, 0))
114     {
115       PG_exception_stack = &local_sigjmp_buf;
116       error_context_stack = NULL;
117 	  set_stack_base();
118 
119       disable_all_timeouts(false);
120       QueryCancelPending = false;
121       pq_comm_reset();
122       EmitErrorReport();
123 
124       AbortCurrentTransaction();
125 
126       PortalErrorCleanup();
127       SPICleanup();
128 
129       jit_reset_after_error();
130 
131       MemoryContextSwitchTo(TopMemoryContext);
132       FlushErrorState();
133 
134       MemoryContextSwitchTo(MessageContext);
135       MemoryContextResetAndDeleteChildren(MessageContext);
136 
137       InvalidateCatalogSnapshotConditionally();
138 
139       SetCurrentStatementStartTimestamp();
140 
141       exec_simple_query(query_string);
142     }
143 
144   free(query_string);
145   return 0;
146 }
147