From ed22b89201143d651f5d13e4fc7e05099788afae Mon Sep 17 00:00:00 2001 From: Wen Xin Date: Thu, 16 Nov 2023 15:38:47 +0800 Subject: [PATCH 1/9] afl-fuzz --- AFL/Makefile | 47 + AFL/afl-as.h | 727 ++++++ AFL/afl-fuzz.c | 6606 +++++++++++++++++++++++++++++++++++++++++++++++ AFL/alloc-inl.h | 577 +++++ AFL/config.h | 357 +++ AFL/debug.h | 258 ++ AFL/hash.h | 111 + AFL/types.h | 94 + 8 files changed, 8777 insertions(+) create mode 100755 AFL/Makefile create mode 100755 AFL/afl-as.h create mode 100755 AFL/afl-fuzz.c create mode 100755 AFL/alloc-inl.h create mode 100755 AFL/config.h create mode 100755 AFL/debug.h create mode 100755 AFL/hash.h create mode 100755 AFL/types.h diff --git a/AFL/Makefile b/AFL/Makefile new file mode 100755 index 0000000..64dca1d --- /dev/null +++ b/AFL/Makefile @@ -0,0 +1,47 @@ +# +# american fuzzy lop - makefile +# ----------------------------- +# +# Written and maintained by Michal Zalewski +# +# Copyright 2013, 2014, 2015, 2016, 2017 Google LLC All rights reserved. +# +# 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 +# + +PROGNAME = afl +VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2) + +#PGSQL_INSTALL_PATH = /mnt/raidhhd/postgrebin_no_instru# Replace with your own path +PGSQL_LIB_PATH = /home/wx/openGauss-server/inst_build/lib +PGSQL_INCLUDE_PATH = /home/wx/openGauss-server/inst_build/include +PREFIX ?= /usr/local +BIN_PATH = $(PREFIX)/bin +HELPER_PATH = $(PREFIX)/lib/afl +DOC_PATH = $(PREFIX)/share/doc/afl +MISC_PATH = $(PREFIX)/share/afl +DEPEN_PATH = ../src/*.cpp ../parser/bison_parser.cpp ../parser/flex_lexer.cpp + +# PROGS intentionally omit afl-as, which gets installed elsewhere. + +PROGS = afl-fuzz + +CC = g++ +CFLAGS ?= -fpermissive --std=c++17 #-fsanitize=address +CFLAGS += -g -w \ + -DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \ + -DBIN_PATH=\"$(BIN_PATH)\" + +COMM_HDR = alloc-inl.h config.h debug.h types.h + +all: $(PROGS) + +afl-fuzz: afl-fuzz.c $(COMM_HDR) + $(CC) $(CFLAGS) -I$(PGSQL_INCLUDE_PATH) -L$(PGSQL_LIB_PATH) -g $@.c $(DEPEN_PATH) -o $@ $(LDFLAGS) -ldl -lpq + +clean: + rm -f afl-fuzz diff --git a/AFL/afl-as.h b/AFL/afl-as.h new file mode 100755 index 0000000..276b8a4 --- /dev/null +++ b/AFL/afl-as.h @@ -0,0 +1,727 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - injectable parts + ------------------------------------- + + Written and maintained by Michal Zalewski + + Forkserver design by Jann Horn + + This file houses the assembly-level instrumentation injected into fuzzed + programs. The instrumentation stores XORed pairs of data: identifiers of the + currently executing branch and the one that executed immediately before. + + TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++ + + The code is designed for 32-bit and 64-bit x86 systems. Both modes should + work everywhere except for Apple systems. Apple does relocations differently + from everybody else, so since their OSes have been 64-bit for a longer while, + I didn't go through the mental effort of porting the 32-bit code. + + In principle, similar code should be easy to inject into any well-behaved + binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural + targets for instrumentation, and should offer comparable probe density. + +*/ + +#ifndef _HAVE_AFL_AS_H +#define _HAVE_AFL_AS_H + +#include "config.h" +#include "types.h" + +/* + ------------------ + Performances notes + ------------------ + + Contributions to make this code faster are appreciated! Here are some + rough notes that may help with the task: + + - Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are + really worth optimizing; the setup / fork server stuff matters a lot less + and should be mostly just kept readable. + + - We're aiming for modern CPUs with out-of-order execution and large + pipelines; the code is mostly follows intuitive, human-readable + instruction ordering, because "textbook" manual reorderings make no + substantial difference. + + - Interestingly, instrumented execution isn't a lot faster if we store a + variable pointer to the setup, log, or return routine and then do a reg + call from within trampoline_fmt. It does speed up non-instrumented + execution quite a bit, though, since that path just becomes + push-call-ret-pop. + + - There is also not a whole lot to be gained by doing SHM attach at a + fixed address instead of retrieving __afl_area_ptr. Although it allows us + to have a shorter log routine inserted for conditional jumps and jump + labels (for a ~10% perf gain), there is a risk of bumping into other + allocations created by the program or by tools such as ASAN. + + - popf is *awfully* slow, which is why we're doing the lahf / sahf + + overflow test trick. Unfortunately, this forces us to taint eax / rax, but + this dependency on a commonly-used register still beats the alternative of + using pushf / popf. + + One possible optimization is to avoid touching flags by using a circular + buffer that stores just a sequence of current locations, with the XOR stuff + happening offline. Alas, this doesn't seem to have a huge impact: + + https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ + + - Preforking one child a bit sooner, and then waiting for the "go" command + from within the child, doesn't offer major performance gains; fork() seems + to be relatively inexpensive these days. Preforking multiple children does + help, but badly breaks the "~1 core per fuzzer" design, making it harder to + scale up. Maybe there is some middle ground. + + Perhaps of note: in the 64-bit version for all platforms except for Apple, + the instrumentation is done slightly differently than on 32-bit, with + __afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm), + rather than global (.comm). This is to avoid GOTRELPC lookups in the critical + code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to + work; simple relocations between .bss and .text won't work on most 64-bit + platforms in such a case. + + (Fun fact: on Apple systems, .lcomm can segfault the linker.) + + The side effect is that state transitions are measured in a somewhat + different way, with previous tuple being recorded separately within the scope + of every .c file. This should have no impact in any practical sense. + + Another side effect of this design is that getenv() will be called once per + every .o file when running in non-instrumented mode; and since getenv() tends + to be optimized in funny ways, we need to be very careful to save every + oddball register it may touch. + + */ + +static const u8* trampoline_fmt_32 = + + "\n" + "/* --- AFL TRAMPOLINE (32-BIT) --- */\n" + "\n" + ".align 4\n" + "\n" + "leal -16(%%esp), %%esp\n" + "movl %%edi, 0(%%esp)\n" + "movl %%edx, 4(%%esp)\n" + "movl %%ecx, 8(%%esp)\n" + "movl %%eax, 12(%%esp)\n" + "movl $0x%08x, %%ecx\n" + "call __afl_maybe_log\n" + "movl 12(%%esp), %%eax\n" + "movl 8(%%esp), %%ecx\n" + "movl 4(%%esp), %%edx\n" + "movl 0(%%esp), %%edi\n" + "leal 16(%%esp), %%esp\n" + "\n" + "/* --- END --- */\n" + "\n"; + +static const u8* trampoline_fmt_64 = + + "\n" + "/* --- AFL TRAMPOLINE (64-BIT) --- */\n" + "\n" + ".align 4\n" + "\n" + "leaq -(128+24)(%%rsp), %%rsp\n" + "movq %%rdx, 0(%%rsp)\n" + "movq %%rcx, 8(%%rsp)\n" + "movq %%rax, 16(%%rsp)\n" + "movq $0x%08x, %%rcx\n" + "call __afl_maybe_log\n" + "movq 16(%%rsp), %%rax\n" + "movq 8(%%rsp), %%rcx\n" + "movq 0(%%rsp), %%rdx\n" + "leaq (128+24)(%%rsp), %%rsp\n" + "\n" + "/* --- END --- */\n" + "\n"; + +static const u8* main_payload_32 = + + "\n" + "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n" + "\n" + ".text\n" + ".att_syntax\n" + ".code32\n" + ".align 8\n" + "\n" + + "__afl_maybe_log:\n" + "\n" + " lahf\n" + " seto %al\n" + "\n" + " /* Check if SHM region is already mapped. */\n" + "\n" + " movl __afl_area_ptr, %edx\n" + " testl %edx, %edx\n" + " je __afl_setup\n" + "\n" + "__afl_store:\n" + "\n" + " /* Calculate and store hit for the code location specified in ecx. There\n" + " is a double-XOR way of doing this without tainting another register,\n" + " and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n" + "\n" +#ifndef COVERAGE_ONLY + " movl __afl_prev_loc, %edi\n" + " xorl %ecx, %edi\n" + " shrl $1, %ecx\n" + " movl %ecx, __afl_prev_loc\n" +#else + " movl %ecx, %edi\n" +#endif /* ^!COVERAGE_ONLY */ + "\n" +#ifdef SKIP_COUNTS + " orb $1, (%edx, %edi, 1)\n" +#else + " incb (%edx, %edi, 1)\n" +#endif /* ^SKIP_COUNTS */ + "\n" + "__afl_return:\n" + "\n" + " addb $127, %al\n" + " sahf\n" + " ret\n" + "\n" + ".align 8\n" + "\n" + "__afl_setup:\n" + "\n" + " /* Do not retry setup if we had previous failures. */\n" + "\n" + " cmpb $0, __afl_setup_failure\n" + " jne __afl_return\n" + "\n" + " /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n" + " We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n" + " will notice this early in the game. */\n" + "\n" + " pushl %eax\n" + " pushl %ecx\n" + "\n" + " pushl $.AFL_SHM_ENV\n" + " call getenv\n" + " addl $4, %esp\n" + "\n" + " testl %eax, %eax\n" + " je __afl_setup_abort\n" + "\n" + " pushl %eax\n" + " call atoi\n" + " addl $4, %esp\n" + "\n" + " pushl $0 /* shmat flags */\n" + " pushl $0 /* requested addr */\n" + " pushl %eax /* SHM ID */\n" + " call shmat\n" + " addl $12, %esp\n" + "\n" + " cmpl $-1, %eax\n" + " je __afl_setup_abort\n" + "\n" + " /* Store the address of the SHM region. */\n" + "\n" + " movl %eax, __afl_area_ptr\n" + " movl %eax, %edx\n" + "\n" + " popl %ecx\n" + " popl %eax\n" + "\n" + "__afl_forkserver:\n" + "\n" + " /* Enter the fork server mode to avoid the overhead of execve() calls. */\n" + "\n" + " pushl %eax\n" + " pushl %ecx\n" + " pushl %edx\n" + "\n" + " /* Phone home and tell the parent that we're OK. (Note that signals with\n" + " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" + " closed because we were execve()d from an instrumented binary, or because\n" + " the parent doesn't want to use the fork server. */\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_temp /* data */\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" + " call write\n" + " addl $12, %esp\n" + "\n" + " cmpl $4, %eax\n" + " jne __afl_fork_resume\n" + "\n" + "__afl_fork_wait_loop:\n" + "\n" + " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_temp /* data */\n" + " pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n" + " call read\n" + " addl $12, %esp\n" + "\n" + " cmpl $4, %eax\n" + " jne __afl_die\n" + "\n" + " /* Once woken up, create a clone of our process. This is an excellent use\n" + " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" + " caches getpid() results and offers no way to update the value, breaking\n" + " abort(), raise(), and a bunch of other things :-( */\n" + "\n" + " call fork\n" + "\n" + " cmpl $0, %eax\n" + " jl __afl_die\n" + " je __afl_fork_resume\n" + "\n" + " /* In parent process: write PID to pipe, then wait for child. */\n" + "\n" + " movl %eax, __afl_fork_pid\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_fork_pid /* data */\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" + " call write\n" + " addl $12, %esp\n" + "\n" + " pushl $0 /* no flags */\n" + " pushl $__afl_temp /* status */\n" + " pushl __afl_fork_pid /* PID */\n" + " call waitpid\n" + " addl $12, %esp\n" + "\n" + " cmpl $0, %eax\n" + " jle __afl_die\n" + "\n" + " /* Relay wait status to pipe, then loop back. */\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_temp /* data */\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" + " call write\n" + " addl $12, %esp\n" + "\n" + " jmp __afl_fork_wait_loop\n" + "\n" + "__afl_fork_resume:\n" + "\n" + " /* In child process: close fds, resume execution. */\n" + "\n" + " pushl $" STRINGIFY(FORKSRV_FD) "\n" + " call close\n" + "\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n" + " call close\n" + "\n" + " addl $8, %esp\n" + "\n" + " popl %edx\n" + " popl %ecx\n" + " popl %eax\n" + " jmp __afl_store\n" + "\n" + "__afl_die:\n" + "\n" + " xorl %eax, %eax\n" + " call _exit\n" + "\n" + "__afl_setup_abort:\n" + "\n" + " /* Record setup failure so that we don't keep calling\n" + " shmget() / shmat() over and over again. */\n" + "\n" + " incb __afl_setup_failure\n" + " popl %ecx\n" + " popl %eax\n" + " jmp __afl_return\n" + "\n" + ".AFL_VARS:\n" + "\n" + " .comm __afl_area_ptr, 4, 32\n" + " .comm __afl_setup_failure, 1, 32\n" +#ifndef COVERAGE_ONLY + " .comm __afl_prev_loc, 4, 32\n" +#endif /* !COVERAGE_ONLY */ + " .comm __afl_fork_pid, 4, 32\n" + " .comm __afl_temp, 4, 32\n" + "\n" + ".AFL_SHM_ENV:\n" + " .asciz \"" SHM_ENV_VAR "\"\n" + "\n" + "/* --- END --- */\n" + "\n"; + +/* The OpenBSD hack is due to lahf and sahf not being recognized by some + versions of binutils: http://marc.info/?l=openbsd-cvs&m=141636589924400 + + The Apple code is a bit different when calling libc functions because + they are doing relocations differently from everybody else. We also need + to work around the crash issue with .lcomm and the fact that they don't + recognize .string. */ + +#ifdef __APPLE__ +# define CALL_L64(str) "call _" str "\n" +#else +# define CALL_L64(str) "call " str "@PLT\n" +#endif /* ^__APPLE__ */ + +static const u8* main_payload_64 = + + "\n" + "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n" + "\n" + ".text\n" + ".att_syntax\n" + ".code64\n" + ".align 8\n" + "\n" + "__afl_maybe_log:\n" + "\n" +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) + " .byte 0x9f /* lahf */\n" +#else + " lahf\n" +#endif /* ^__OpenBSD__, etc */ + " seto %al\n" + "\n" + " /* Check if SHM region is already mapped. */\n" + "\n" + " movq __afl_area_ptr(%rip), %rdx\n" + " testq %rdx, %rdx\n" + " je __afl_setup\n" + "\n" + "__afl_store:\n" + "\n" + " /* Calculate and store hit for the code location specified in rcx. */\n" + "\n" +#ifndef COVERAGE_ONLY + " xorq __afl_prev_loc(%rip), %rcx\n" + " xorq %rcx, __afl_prev_loc(%rip)\n" + " shrq $1, __afl_prev_loc(%rip)\n" +#endif /* ^!COVERAGE_ONLY */ + "\n" +#ifdef SKIP_COUNTS + " orb $1, (%rdx, %rcx, 1)\n" +#else + " incb (%rdx, %rcx, 1)\n" +#endif /* ^SKIP_COUNTS */ + "\n" + "__afl_return:\n" + "\n" + " addb $127, %al\n" +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) + " .byte 0x9e /* sahf */\n" +#else + " sahf\n" +#endif /* ^__OpenBSD__, etc */ + " ret\n" + "\n" + ".align 8\n" + "\n" + "__afl_setup:\n" + "\n" + " /* Do not retry setup if we had previous failures. */\n" + "\n" + " cmpb $0, __afl_setup_failure(%rip)\n" + " jne __afl_return\n" + "\n" + " /* Check out if we have a global pointer on file. */\n" + "\n" +#ifndef __APPLE__ + " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" + " movq (%rdx), %rdx\n" +#else + " movq __afl_global_area_ptr(%rip), %rdx\n" +#endif /* !^__APPLE__ */ + " testq %rdx, %rdx\n" + " je __afl_setup_first\n" + "\n" + " movq %rdx, __afl_area_ptr(%rip)\n" + " jmp __afl_store\n" + "\n" + "__afl_setup_first:\n" + "\n" + " /* Save everything that is not yet saved and that may be touched by\n" + " getenv() and several other libcalls we'll be relying on. */\n" + "\n" + " leaq -352(%rsp), %rsp\n" + "\n" + " movq %rax, 0(%rsp)\n" + " movq %rcx, 8(%rsp)\n" + " movq %rdi, 16(%rsp)\n" + " movq %rsi, 32(%rsp)\n" + " movq %r8, 40(%rsp)\n" + " movq %r9, 48(%rsp)\n" + " movq %r10, 56(%rsp)\n" + " movq %r11, 64(%rsp)\n" + "\n" + " movq %xmm0, 96(%rsp)\n" + " movq %xmm1, 112(%rsp)\n" + " movq %xmm2, 128(%rsp)\n" + " movq %xmm3, 144(%rsp)\n" + " movq %xmm4, 160(%rsp)\n" + " movq %xmm5, 176(%rsp)\n" + " movq %xmm6, 192(%rsp)\n" + " movq %xmm7, 208(%rsp)\n" + " movq %xmm8, 224(%rsp)\n" + " movq %xmm9, 240(%rsp)\n" + " movq %xmm10, 256(%rsp)\n" + " movq %xmm11, 272(%rsp)\n" + " movq %xmm12, 288(%rsp)\n" + " movq %xmm13, 304(%rsp)\n" + " movq %xmm14, 320(%rsp)\n" + " movq %xmm15, 336(%rsp)\n" + "\n" + " /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n" + "\n" + " /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n" + " original stack ptr in the callee-saved r12. */\n" + "\n" + " pushq %r12\n" + " movq %rsp, %r12\n" + " subq $16, %rsp\n" + " andq $0xfffffffffffffff0, %rsp\n" + "\n" + " leaq .AFL_SHM_ENV(%rip), %rdi\n" + CALL_L64("getenv") + "\n" + " testq %rax, %rax\n" + " je __afl_setup_abort\n" + "\n" + " movq %rax, %rdi\n" + CALL_L64("atoi") + "\n" + " xorq %rdx, %rdx /* shmat flags */\n" + " xorq %rsi, %rsi /* requested addr */\n" + " movq %rax, %rdi /* SHM ID */\n" + CALL_L64("shmat") + "\n" + " cmpq $-1, %rax\n" + " je __afl_setup_abort\n" + "\n" + " /* Store the address of the SHM region. */\n" + "\n" + " movq %rax, %rdx\n" + " movq %rax, __afl_area_ptr(%rip)\n" + "\n" +#ifdef __APPLE__ + " movq %rax, __afl_global_area_ptr(%rip)\n" +#else + " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" + " movq %rax, (%rdx)\n" +#endif /* ^__APPLE__ */ + " movq %rax, %rdx\n" + "\n" + "__afl_forkserver:\n" + "\n" + " /* Enter the fork server mode to avoid the overhead of execve() calls. We\n" + " push rdx (area ptr) twice to keep stack alignment neat. */\n" + "\n" + " pushq %rdx\n" + " pushq %rdx\n" + "\n" + " /* Phone home and tell the parent that we're OK. (Note that signals with\n" + " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" + " closed because we were execve()d from an instrumented binary, or because\n" + " the parent doesn't want to use the fork server. */\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_temp(%rip), %rsi /* data */\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" + CALL_L64("write") + "\n" + " cmpq $4, %rax\n" + " jne __afl_fork_resume\n" + "\n" + "__afl_fork_wait_loop:\n" + "\n" + " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_temp(%rip), %rsi /* data */\n" + " movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n" + CALL_L64("read") + " cmpq $4, %rax\n" + " jne __afl_die\n" + "\n" + " /* Once woken up, create a clone of our process. This is an excellent use\n" + " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" + " caches getpid() results and offers no way to update the value, breaking\n" + " abort(), raise(), and a bunch of other things :-( */\n" + "\n" + CALL_L64("fork") + " cmpq $0, %rax\n" + " jl __afl_die\n" + " je __afl_fork_resume\n" + "\n" + " /* In parent process: write PID to pipe, then wait for child. */\n" + "\n" + " movl %eax, __afl_fork_pid(%rip)\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_fork_pid(%rip), %rsi /* data */\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" + CALL_L64("write") + "\n" + " movq $0, %rdx /* no flags */\n" + " leaq __afl_temp(%rip), %rsi /* status */\n" + " movq __afl_fork_pid(%rip), %rdi /* PID */\n" + CALL_L64("waitpid") + " cmpq $0, %rax\n" + " jle __afl_die\n" + "\n" + " /* Relay wait status to pipe, then loop back. */\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_temp(%rip), %rsi /* data */\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" + CALL_L64("write") + "\n" + " jmp __afl_fork_wait_loop\n" + "\n" + "__afl_fork_resume:\n" + "\n" + " /* In child process: close fds, resume execution. */\n" + "\n" + " movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n" + CALL_L64("close") + "\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n" + CALL_L64("close") + "\n" + " popq %rdx\n" + " popq %rdx\n" + "\n" + " movq %r12, %rsp\n" + " popq %r12\n" + "\n" + " movq 0(%rsp), %rax\n" + " movq 8(%rsp), %rcx\n" + " movq 16(%rsp), %rdi\n" + " movq 32(%rsp), %rsi\n" + " movq 40(%rsp), %r8\n" + " movq 48(%rsp), %r9\n" + " movq 56(%rsp), %r10\n" + " movq 64(%rsp), %r11\n" + "\n" + " movq 96(%rsp), %xmm0\n" + " movq 112(%rsp), %xmm1\n" + " movq 128(%rsp), %xmm2\n" + " movq 144(%rsp), %xmm3\n" + " movq 160(%rsp), %xmm4\n" + " movq 176(%rsp), %xmm5\n" + " movq 192(%rsp), %xmm6\n" + " movq 208(%rsp), %xmm7\n" + " movq 224(%rsp), %xmm8\n" + " movq 240(%rsp), %xmm9\n" + " movq 256(%rsp), %xmm10\n" + " movq 272(%rsp), %xmm11\n" + " movq 288(%rsp), %xmm12\n" + " movq 304(%rsp), %xmm13\n" + " movq 320(%rsp), %xmm14\n" + " movq 336(%rsp), %xmm15\n" + "\n" + " leaq 352(%rsp), %rsp\n" + "\n" + " jmp __afl_store\n" + "\n" + "__afl_die:\n" + "\n" + " xorq %rax, %rax\n" + CALL_L64("_exit") + "\n" + "__afl_setup_abort:\n" + "\n" + " /* Record setup failure so that we don't keep calling\n" + " shmget() / shmat() over and over again. */\n" + "\n" + " incb __afl_setup_failure(%rip)\n" + "\n" + " movq %r12, %rsp\n" + " popq %r12\n" + "\n" + " movq 0(%rsp), %rax\n" + " movq 8(%rsp), %rcx\n" + " movq 16(%rsp), %rdi\n" + " movq 32(%rsp), %rsi\n" + " movq 40(%rsp), %r8\n" + " movq 48(%rsp), %r9\n" + " movq 56(%rsp), %r10\n" + " movq 64(%rsp), %r11\n" + "\n" + " movq 96(%rsp), %xmm0\n" + " movq 112(%rsp), %xmm1\n" + " movq 128(%rsp), %xmm2\n" + " movq 144(%rsp), %xmm3\n" + " movq 160(%rsp), %xmm4\n" + " movq 176(%rsp), %xmm5\n" + " movq 192(%rsp), %xmm6\n" + " movq 208(%rsp), %xmm7\n" + " movq 224(%rsp), %xmm8\n" + " movq 240(%rsp), %xmm9\n" + " movq 256(%rsp), %xmm10\n" + " movq 272(%rsp), %xmm11\n" + " movq 288(%rsp), %xmm12\n" + " movq 304(%rsp), %xmm13\n" + " movq 320(%rsp), %xmm14\n" + " movq 336(%rsp), %xmm15\n" + "\n" + " leaq 352(%rsp), %rsp\n" + "\n" + " jmp __afl_return\n" + "\n" + ".AFL_VARS:\n" + "\n" + +#ifdef __APPLE__ + + " .comm __afl_area_ptr, 8\n" +#ifndef COVERAGE_ONLY + " .comm __afl_prev_loc, 8\n" +#endif /* !COVERAGE_ONLY */ + " .comm __afl_fork_pid, 4\n" + " .comm __afl_temp, 4\n" + " .comm __afl_setup_failure, 1\n" + +#else + + " .lcomm __afl_area_ptr, 8\n" +#ifndef COVERAGE_ONLY + " .lcomm __afl_prev_loc, 8\n" +#endif /* !COVERAGE_ONLY */ + " .lcomm __afl_fork_pid, 4\n" + " .lcomm __afl_temp, 4\n" + " .lcomm __afl_setup_failure, 1\n" + +#endif /* ^__APPLE__ */ + + " .comm __afl_global_area_ptr, 8, 8\n" + "\n" + ".AFL_SHM_ENV:\n" + " .asciz \"" SHM_ENV_VAR "\"\n" + "\n" + "/* --- END --- */\n" + "\n"; + +#endif /* !_HAVE_AFL_AS_H */ diff --git a/AFL/afl-fuzz.c b/AFL/afl-fuzz.c new file mode 100755 index 0000000..c024cb2 --- /dev/null +++ b/AFL/afl-fuzz.c @@ -0,0 +1,6606 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - fuzzer code + -------------------------------- + + Written and maintained by Michal Zalewski + + Forkserver design by Jann Horn + + This is the real deal: the program takes an instrumented binary and + attempts a variety of basic fuzzing tricks, paying close attention to + how they affect the execution path. + +*/ + +#define AFL_MAIN +#define MESSAGES_TO_STDOUT + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#define _FILE_OFFSET_BITS 64 + +#include "config.h" +#include "types.h" +#include "debug.h" +#include "alloc-inl.h" +#include "hash.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../include/ast.h" +#include "../include/mutate.h" +#include "../include//instantiate.h" +#include "../include/define.h" +#include "../include/connector.h" + +using namespace std; +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) +# include +#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ + +/* For systems that have sched_setaffinity; right now just Linux, but one + can hope... */ + +#ifdef __linux__ +# define HAVE_AFFINITY 1 +#endif /* __linux__ */ + +/* A toggle to export some variables when building as a library. Not very + useful for the general public. */ + +#ifdef AFL_LIB +# define EXP_ST +#else +# define EXP_ST static +#endif /* ^AFL_LIB */ + +/* Lots of globals, but mostly for the status UI and other things where it + really makes no sense to haul them around as function parameters. */ + +#define ABPATH "/home/omm/openGauss_Fuzzer_release/" +#define RLPATH_LIB "/corpus/initlib" +#define RLPATH_IRINFO "/corpus/IR_config" +#define RLPATH_OUTPUT "/" + +#define INIT_LIB ABPATH RLPATH_LIB +#define GRAMMAR_INFORMATION ABPATH RLPATH_IRINFO +#define OUTPUT_PATH ABPATH RLPATH_OUTPUT + +#define HOST "localhost" +#define USERNAME "omm" +#define PASSWORD "Aa1!@#$%^&*()" +#define PORT 5432 + +#define SERVERNAME "gaussdb" +const char* file = "/home/wx/openGauss-server/inst_build/bin/gs_ctl"; +char* const options[] = { "/home/wx/openGauss-server/inst_build/bin/gs_ctl", "start", "-D", "/home/omm/data", "-Z", "single_node", "-l", "/home/omm/log/opengauss.log", NULL }; + +static long seed_count = 0; + +char* g_current_sql = nullptr; +InputInfo* g_current_input = nullptr; + +Mutator g_mutator; +Instantiator g_instantiator; +Connector g_connector(HOST, USERNAME, PASSWORD, PORT, SERVERNAME); + +EXP_ST u8 vaild_flag = 0; +EXP_ST u64 total_vaild = 0; + +EXP_ST u8 *in_dir, /* Input directory with test cases */ + *out_file, /* File to fuzz, if any */ + *out_dir, /* Working & output directory */ + *sync_dir, /* Synchronization directory */ + *sync_id, /* Fuzzer ID */ + *use_banner, /* Display banner */ + *in_bitmap, /* Input bitmap */ + *doc_path, /* Path to documentation dir */ + *target_path, /* Path to target binary */ + *orig_cmdline; /* Original command line */ + +EXP_ST u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */ +static u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */ + +EXP_ST u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */ + +static u32 stats_update_freq = 1; /* Stats update frequency (execs) */ + +EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */ + force_deterministic, /* Force deterministic stages? */ + use_splicing, /* Recombine input files? */ + dumb_mode, /* Run in non-instrumented mode? */ + score_changed, /* Scoring for favorites changed? */ + kill_signal, /* Signal that killed the child */ + resuming_fuzz, /* Resuming an older fuzzing job? */ + timeout_given, /* Specific timeout given? */ + not_on_tty, /* stdout is not a tty */ + term_too_small, /* terminal dimensions too small */ + uses_asan, /* Target uses ASAN? */ + no_forkserver, /* Disable forkserver? */ + crash_mode, /* Crash mode! Yeah! */ + in_place_resume, /* Attempt in-place resume? */ + auto_changed, /* Auto-generated tokens changed? */ + no_cpu_meter_red, /* Feng shui on the status screen */ + no_arith, /* Skip most arithmetic ops */ + shuffle_queue, /* Shuffle input queue? */ + bitmap_changed = 1, /* Time to update bitmap? */ + qemu_mode, /* Running in QEMU mode? */ + skip_requested, /* Skip request, via SIGUSR1 */ + run_over10m, /* Run time over 10 minutes? */ + persistent_mode, /* Running in persistent mode? */ + deferred_mode, /* Deferred forkserver mode? */ + fast_cal; /* Try to calibrate faster? */ + +static s32 out_fd, /* Persistent fd for out_file */ + dev_urandom_fd = -1, /* Persistent fd for /dev/urandom */ + dev_null_fd = -1, /* Persistent fd for /dev/null */ + fsrv_ctl_fd, /* Fork server control pipe (write) */ + fsrv_st_fd; /* Fork server status pipe (read) */ + +static s32 forksrv_pid, /* PID of the fork server */ + child_pid = -1, /* PID of the fuzzed program */ + out_dir_fd = -1; /* FD of the lock file */ + +EXP_ST u8* trace_bits; /* SHM with instrumentation bitmap */ + +EXP_ST u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ + virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ + virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */ + +static u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ + +static s32 shm_id; /* ID of the SHM region */ + +static volatile u8 stop_soon, /* Ctrl-C pressed? */ + clear_screen = 1, /* Window resized? */ + child_timed_out; /* Traced process timed out? */ + +EXP_ST u32 queued_paths, /* Total number of queued testcases */ + queued_variable, /* Testcases with variable behavior */ + queued_at_start, /* Total number of initial inputs */ + queued_discovered, /* Items discovered during this run */ + queued_imported, /* Items imported via -S */ + queued_favored, /* Paths deemed favorable */ + queued_with_cov, /* Paths with new coverage bytes */ + pending_not_fuzzed, /* Queued but not done yet */ + pending_favored, /* Pending favored paths */ + cur_skipped_paths, /* Abandoned inputs in cur cycle */ + cur_depth, /* Current path depth */ + max_depth, /* Max path depth */ + useless_at_start, /* Number of useless starting paths */ + var_byte_count, /* Bitmap bytes with var behavior */ + current_entry, /* Current queue entry ID */ + havoc_div = 1; /* Cycle count divisor for havoc */ + +EXP_ST u64 total_crashes, /* Total number of crashes */ + unique_crashes, /* Crashes with unique signatures */ + total_tmouts, /* Total number of timeouts */ + unique_tmouts, /* Timeouts with unique signatures */ + unique_hangs, /* Hangs with unique signatures */ + total_execs, /* Total execve() calls */ + cur_execs, + slowest_exec_ms, /* Slowest testcase non hang in ms */ + start_time, /* Unix start time (ms) */ + last_save_time, + last_path_time, /* Time for most recent path (ms) */ + last_crash_time, /* Time for most recent crash (ms) */ + last_hang_time, /* Time for most recent hang (ms) */ + last_crash_execs, /* Exec counter at last crash */ + queue_cycle, /* Queue round counter */ + cycles_wo_finds, /* Cycles without any new paths */ + trim_execs, /* Execs done to trim input files */ + bytes_trim_in, /* Bytes coming into the trimmer */ + bytes_trim_out, /* Bytes coming outa the trimmer */ + blocks_eff_total, /* Blocks subject to effector maps */ + blocks_eff_select; /* Blocks selected as fuzzable */ + +static u32 subseq_tmouts; /* Number of timeouts in a row */ + +static u8 *stage_name = "init", /* Name of the current fuzz stage */ + *stage_short, /* Short stage name */ + *syncing_party; /* Currently syncing with... */ + +static s32 stage_cur, stage_max; /* Stage progression */ +static s32 splicing_with = -1; /* Splicing with which test case? */ + +static u32 master_id, master_max; /* Master instance job splitting */ + +static u32 syncing_case; /* Syncing with case #... */ + +static s32 stage_cur_byte, /* Byte offset of current stage op */ + stage_cur_val; /* Value used for stage op */ + +static u8 stage_val_type; /* Value type (STAGE_VAL_*) */ + +static u64 stage_finds[32], /* Patterns found per fuzz stage */ + stage_cycles[32]; /* Execs per fuzz stage */ + +static u32 rand_cnt; /* Random number counter */ + +static u64 total_cal_us, /* Total calibration time (us) */ + total_cal_cycles = 1; /* Total calibration cycles */ + +static u64 total_bitmap_size, /* Total bit count for all bitmaps */ + total_bitmap_entries; /* Number of bitmaps counted */ + +static s32 cpu_core_count; /* CPU core count */ + +#ifdef HAVE_AFFINITY + +static s32 cpu_aff = -1; /* Selected CPU core */ + +#endif /* HAVE_AFFINITY */ + +static FILE* plot_file; /* Gnuplot output file */ + +struct queue_entry { + + u8* fname; /* File name for the test case */ + u32 len; /* Input length */ + + u8 cal_failed, /* Calibration failed? */ + trim_done, /* Trimmed? */ + was_fuzzed, /* Had any fuzzing done yet? */ + passed_det, /* Deterministic stages passed? */ + has_new_cov, /* Triggers new coverage? */ + var_behavior, /* Variable behavior? */ + favored, /* Currently favored? */ + fs_redundant; /* Marked as redundant in the fs? */ + + u32 bitmap_size, /* Number of bits set in bitmap */ + exec_cksum; /* Checksum of the execution trace */ + + u64 exec_us, /* Execution time (us) */ + handicap, /* Number of queue cycles behind */ + depth; /* Path depth */ + + u8* trace_mini; /* Trace bytes, if kept */ + u32 tc_ref; /* Trace bytes ref count */ + + struct queue_entry *next, /* Next element, if any */ + *next_100; /* 100 elements ahead */ + +}; + + +static struct queue_entry *queue, /* Fuzzing queue (linked list) */ + *queue_cur, /* Current offset within the queue */ + *queue_top, /* Top of the list */ + *q_prev100; /* Previous 100 marker */ + +static struct queue_entry* + top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */ + +struct extra_data { + u8* data; /* Dictionary token data */ + u32 len; /* Dictionary token length */ + u32 hit_cnt; /* Use count in the corpus */ +}; + +static struct extra_data* extras; /* Extra tokens to fuzz with */ +static u32 extras_cnt; /* Total number of tokens read */ + +static struct extra_data* a_extras; /* Automatically selected extras */ +static u32 a_extras_cnt; /* Total number of tokens available */ + +static u8* (*post_handler)(u8* buf, u32* len); + +/* Interesting values, as per config.h */ + +static s8 interesting_8[] = { INTERESTING_8 }; +static s16 interesting_16[] = { INTERESTING_8, INTERESTING_16 }; +static s32 interesting_32[] = { INTERESTING_8, INTERESTING_16, INTERESTING_32 }; + +/* Fuzzing stages */ + +enum { + /* 00 */ STAGE_FLIP1, + /* 01 */ STAGE_FLIP2, + /* 02 */ STAGE_FLIP4, + /* 03 */ STAGE_FLIP8, + /* 04 */ STAGE_FLIP16, + /* 05 */ STAGE_FLIP32, + /* 06 */ STAGE_ARITH8, + /* 07 */ STAGE_ARITH16, + /* 08 */ STAGE_ARITH32, + /* 09 */ STAGE_INTEREST8, + /* 10 */ STAGE_INTEREST16, + /* 11 */ STAGE_INTEREST32, + /* 12 */ STAGE_EXTRAS_UO, + /* 13 */ STAGE_EXTRAS_UI, + /* 14 */ STAGE_EXTRAS_AO, + /* 15 */ STAGE_HAVOC, + /* 16 */ STAGE_SPLICE +}; + +/* Stage value types */ + +enum { + /* 00 */ STAGE_VAL_NONE, + /* 01 */ STAGE_VAL_LE, + /* 02 */ STAGE_VAL_BE +}; + +/* Execution status fault codes */ + +enum { + /* 00 */ FAULT_NONE, + /* 01 */ FAULT_TMOUT, + /* 02 */ FAULT_CRASH, + /* 03 */ FAULT_ERROR, + /* 04 */ FAULT_NOINST, + /* 05 */ FAULT_NOBITS +}; + + +/* Get unix time in milliseconds */ +static u64 get_cur_time(void) { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); + +} + +/* Get unix time in microseconds */ + +static u64 get_cur_time_us(void) { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return (tv.tv_sec * 1000000ULL) + tv.tv_usec; + +} + + +/* Generate a random number (from 0 to limit - 1). This may + have slight bias. */ + +static inline u32 UR(u32 limit) { + + if (unlikely(!rand_cnt--)) { + + u32 seed[2]; + + ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom"); + + srandom(seed[0]); + rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG); + + } + + return random() % limit; + +} + + +/* Shuffle an array of pointers. Might be slightly biased. */ + +static void shuffle_ptrs(void** ptrs, u32 cnt) { + + u32 i; + + for (i = 0; i < cnt - 2; i++) { + + u32 j = i + UR(cnt - i); + void *s = ptrs[i]; + ptrs[i] = ptrs[j]; + ptrs[j] = s; + + } + +} + + +#ifdef HAVE_AFFINITY + +/* Build a list of processes bound to specific cores. Returns -1 if nothing + can be found. Assumes an upper bound of 4k CPUs. */ + +static void bind_to_free_cpu(void) { + + DIR* d; + struct dirent* de; + cpu_set_t c; + + u8 cpu_used[4096] = { 0 }; + u32 i; + + if (cpu_core_count < 2) return; + + if (getenv("AFL_NO_AFFINITY")) { + + WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set)."); + return; + + } + + d = opendir("/proc"); + + if (!d) { + + WARNF("Unable to access /proc - can't scan for free CPU cores."); + return; + + } + + ACTF("Checking CPU core loadout..."); + + /* Introduce some jitter, in case multiple AFL tasks are doing the same + thing at the same time... */ + + usleep(R(1000) * 250); + + /* Scan all /proc//status entries, checking for Cpus_allowed_list. + Flag all processes bound to a specific CPU using cpu_used[]. This will + fail for some exotic binding setups, but is likely good enough in almost + all real-world use cases. */ + + while ((de = readdir(d))) { + + u8* fn; + FILE* f; + u8 tmp[MAX_LINE]; + u8 has_vmsize = 0; + + if (!isdigit(de->d_name[0])) continue; + + fn = alloc_printf("/proc/%s/status", de->d_name); + + if (!(f = fopen(fn, "r"))) { + ck_free(fn); + continue; + } + + while (fgets(tmp, MAX_LINE, f)) { + + u32 hval; + + /* Processes without VmSize are probably kernel tasks. */ + + if (!strncmp(tmp, "VmSize:\t", 8)) has_vmsize = 1; + + if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && + !strchr((char *)tmp, int('-')) && !strchr((char *)tmp, int(',')) && + sscanf(tmp + 19, "%u", &hval) == 1 && hval < sizeof(cpu_used) && + has_vmsize) { + + cpu_used[hval] = 1; + break; + + } + + } + + ck_free(fn); + fclose(f); + + } + + closedir(d); + + for (i = 0; i < cpu_core_count; i++) if (!cpu_used[i]) break; + + if (i == cpu_core_count) { + + SAYF("\n" cLRD "[-] " cRST + "Uh-oh, looks like all %u CPU cores on your system are allocated to\n" + " other instances of afl-fuzz (or similar CPU-locked tasks). Starting\n" + " another fuzzer on this machine is probably a bad plan, but if you are\n" + " absolutely sure, you can set AFL_NO_AFFINITY and try again.\n", + cpu_core_count); + + FATAL("No more free CPU cores"); + + } + + OKF("Found a free CPU core, binding to #%u.", i); + + cpu_aff = i; + + CPU_ZERO(&c); + CPU_SET(i, &c); + + if (sched_setaffinity(0, sizeof(c), &c)) + PFATAL("sched_setaffinity failed"); + +} + +#endif /* HAVE_AFFINITY */ + +#ifndef IGNORE_FINDS + +/* Helper function to compare buffers; returns first and last differing offset. We + use this to find reasonable locations for splicing two files. */ + +static void locate_diffs(u8* ptr1, u8* ptr2, u32 len, s32* first, s32* last) { + + s32 f_loc = -1; + s32 l_loc = -1; + u32 pos; + + for (pos = 0; pos < len; pos++) { + + if (*(ptr1++) != *(ptr2++)) { + + if (f_loc == -1) f_loc = pos; + l_loc = pos; + + } + + } + + *first = f_loc; + *last = l_loc; + + return; + +} + +#endif /* !IGNORE_FINDS */ + + +/* Describe integer. Uses 12 cyclic static buffers for return values. The value + returned should be five characters or less for all the integers we reasonably + expect to see. */ + +static u8* DI(u64 val) { + + static u8 tmp[12][16]; + static u8 cur; + + cur = (cur + 1) % 12; + +#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) do { \ + if (val < (_divisor) * (_limit_mult)) { \ + sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \ + return tmp[cur]; \ + } \ + } while (0) + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1000, 99.95, "%0.01fk", double); + + /* 100k - 999k */ + CHK_FORMAT(1000, 1000, "%lluk", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); + + /* 100M - 999M */ + CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); + + /* 100G - 999G */ + CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); + + /* 100T+ */ + strcpy(tmp[cur], "infty"); + return tmp[cur]; + +} + + +/* Describe float. Similar to the above, except with a single + static buffer. */ + +static u8* DF(double val) { + + static u8 tmp[16]; + + if (val < 99.995) { + sprintf(tmp, "%0.02f", val); + return tmp; + } + + if (val < 999.95) { + sprintf(tmp, "%0.01f", val); + return tmp; + } + + return DI((u64)val); + +} + + +/* Describe integer as memory size. */ + +static u8* DMS(u64 val) { + + static u8 tmp[12][16]; + static u8 cur; + + cur = (cur + 1) % 12; + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu B", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1024, 99.95, "%0.01f kB", double); + + /* 100k - 999k */ + CHK_FORMAT(1024, 1000, "%llu kB", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); + + /* 100M - 999M */ + CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); + + /* 100G - 999G */ + CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); + +#undef CHK_FORMAT + + /* 100T+ */ + strcpy(tmp[cur], "infty"); + return tmp[cur]; + +} + + +/* Describe time delta. Returns one static buffer, 34 chars of less. */ + +static u8* DTD(u64 cur_ms, u64 event_ms) { + + static u8 tmp[64]; + u64 delta; + s32 t_d, t_h, t_m, t_s; + + if (!event_ms) return "none seen yet"; + + delta = cur_ms - event_ms; + + t_d = delta / 1000 / 60 / 60 / 24; + t_h = (delta / 1000 / 60 / 60) % 24; + t_m = (delta / 1000 / 60) % 60; + t_s = (delta / 1000) % 60; + + sprintf(tmp, "%s days, %u hrs, %u min, %u sec", DI(t_d), t_h, t_m, t_s); + return tmp; + +} + + +/* Mark deterministic checks as done for a particular queue entry. We use the + .state file to avoid repeating deterministic fuzzing when resuming aborted + scans. */ + +static void mark_as_det_done(struct queue_entry* q) { + + u8* fn = strrchr((const char*)q->fname, '/'); + s32 fd; + + fn = alloc_printf("%s/queue/.state/deterministic_done/%s", out_dir, fn + 1); + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + close(fd); + + ck_free(fn); + + q->passed_det = 1; + +} + + +/* Mark as variable. Create symlinks if possible to make it easier to examine + the files. */ + +static void mark_as_variable(struct queue_entry* q) { + + u8 *fn = strrchr((char *)q->fname, '/') + 1, *ldest; + + ldest = alloc_printf("../../%s", fn); + fn = alloc_printf("%s/queue/.state/variable_behavior/%s", out_dir, fn); + + if (symlink(ldest, fn)) { + + s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + close(fd); + + } + + ck_free(ldest); + ck_free(fn); + + q->var_behavior = 1; + +} + + +/* Mark / unmark as redundant (edge-only). This is not used for restoring state, + but may be useful for post-processing datasets. */ + +static void mark_as_redundant(struct queue_entry* q, u8 state) { + + u8* fn; + s32 fd; + + if (state == q->fs_redundant) return; + + q->fs_redundant = state; + + fn = strrchr((const char*)q->fname, '/'); + fn = alloc_printf("%s/queue/.state/redundant_edges/%s", out_dir, fn + 1); + + if (state) { + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + close(fd); + + } else { + + if (unlink(fn)) PFATAL("Unable to remove '%s'", fn); + + } + + ck_free(fn); + +} + + +/* Append new test case to the queue. */ + +static void add_to_queue(u8* fname, u32 len, u8 passed_det) { + + struct queue_entry* q = ck_alloc(sizeof(struct queue_entry)); + + q->fname = fname; + q->len = len; + q->depth = cur_depth + 1; + q->passed_det = passed_det; + + if (q->depth > max_depth) max_depth = q->depth; + + if (queue_top) { + + queue_top->next = q; + queue_top = q; + + } else q_prev100 = queue = queue_top = q; + + queued_paths++; + pending_not_fuzzed++; + + cycles_wo_finds = 0; + + if (!(queued_paths % 100)) { + + q_prev100->next_100 = q; + q_prev100 = q; + + } + + last_path_time = get_cur_time(); + +} + + +/* Destroy the entire queue. */ + +EXP_ST void destroy_queue(void) { + + struct queue_entry *q = queue, *n; + + while (q) { + + n = q->next; + ck_free(q->fname); + ck_free(q->trace_mini); + ck_free(q); + q = n; + + } + +} + + +/* Write bitmap to file. The bitmap is useful mostly for the secret + -B option, to focus a separate fuzzing session on a particular + interesting input without rediscovering all the others. */ + +EXP_ST void write_bitmap(void) { + + u8* fname; + s32 fd; + + if (!bitmap_changed) return; + bitmap_changed = 0; + + fname = alloc_printf("%s/fuzz_bitmap", out_dir); + fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to open '%s'", fname); + + ck_write(fd, virgin_bits, MAP_SIZE, fname); + + close(fd); + ck_free(fname); + +} + + +/* Read bitmap from file. This is for the -B option again. */ + +EXP_ST void read_bitmap(u8* fname) { + + s32 fd = open(fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", fname); + + ck_read(fd, virgin_bits, MAP_SIZE, fname); + + close(fd); + +} + + +/* Check if the current execution path brings anything new to the table. + Update virgin bits to reflect the finds. Returns 1 if the only change is + the hit-count for a particular tuple; 2 if there are new tuples seen. + Updates the map, so subsequent calls will always return 0. + + This function is called after every exec() on a fairly large buffer, so + it needs to be fast. We do this in 32-bit and 64-bit flavors. */ + +static inline u8 has_new_bits(u8* virgin_map) { + +#ifdef __x86_64__ + + u64* current = (u64*)trace_bits; + u64* virgin = (u64*)virgin_map; + + u32 i = (MAP_SIZE >> 3); + +#else + + u32* current = (u32*)trace_bits; + u32* virgin = (u32*)virgin_map; + + u32 i = (MAP_SIZE >> 2); + +#endif /* ^__x86_64__ */ + + u8 ret = 0; + + while (i--) { + + /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap + that have not been already cleared from the virgin map - since this will + almost always be the case. */ + + if (unlikely(*current) && unlikely(*current & *virgin)) { + + if (likely(ret < 2)) { + + u8* cur = (u8*)current; + u8* vir = (u8*)virgin; + + /* Looks like we have not found any new bytes yet; see if any non-zero + bytes in current[] are pristine in virgin[]. */ + +#ifdef __x86_64__ + + if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || + (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || + (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || + (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) ret = 2; + else ret = 1; + +#else + + if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || + (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) ret = 2; + else ret = 1; + +#endif /* ^__x86_64__ */ + + } + + *virgin &= ~*current; + + } + + current++; + virgin++; + + } + + if (ret && virgin_map == virgin_bits) bitmap_changed = 1; + + return ret; + +} + + +/* Count the number of bits set in the provided bitmap. Used for the status + screen several times every second, does not have to be fast. */ + +static u32 count_bits(u8* mem) { + + u32* ptr = (u32*)mem; + u32 i = (MAP_SIZE >> 2); + u32 ret = 0; + + while (i--) { + + u32 v = *(ptr++); + + /* This gets called on the inverse, virgin bitmap; optimize for sparse + data. */ + + if (v == 0xffffffff) { + ret += 32; + continue; + } + + v -= ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; + + } + + return ret; + +} + + +#define FF(_b) (0xff << ((_b) << 3)) + +/* Count the number of bytes set in the bitmap. Called fairly sporadically, + mostly to update the status screen or calibrate and examine confirmed + new paths. */ + +static u32 count_bytes(u8* mem) { + + u32* ptr = (u32*)mem; + u32 i = (MAP_SIZE >> 2); + u32 ret = 0; + + while (i--) { + + u32 v = *(ptr++); + + if (!v) continue; + if (v & FF(0)) ret++; + if (v & FF(1)) ret++; + if (v & FF(2)) ret++; + if (v & FF(3)) ret++; + + } + + return ret; + +} + + +/* Count the number of non-255 bytes set in the bitmap. Used strictly for the + status screen, several calls per second or so. */ + +static u32 count_non_255_bytes(u8* mem) { + + u32* ptr = (u32*)mem; + u32 i = (MAP_SIZE >> 2); + u32 ret = 0; + + while (i--) { + + u32 v = *(ptr++); + + /* This is called on the virgin bitmap, so optimize for the most likely + case. */ + + if (v == 0xffffffff) continue; + if ((v & FF(0)) != FF(0)) ret++; + if ((v & FF(1)) != FF(1)) ret++; + if ((v & FF(2)) != FF(2)) ret++; + if ((v & FF(3)) != FF(3)) ret++; + + } + + return ret; + +} + + +/* Destructively simplify trace by eliminating hit count information + and replacing it with 0x80 or 0x01 depending on whether the tuple + is hit or not. Called on every new crash or timeout, should be + reasonably fast. */ + +static u8 simplify_lookup[256] = {0}; + +#ifdef __x86_64__ + +static void simplify_trace(u64* mem) { + + u32 i = MAP_SIZE >> 3; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u8* mem8 = (u8*)mem; + + mem8[0] = simplify_lookup[mem8[0]]; + mem8[1] = simplify_lookup[mem8[1]]; + mem8[2] = simplify_lookup[mem8[2]]; + mem8[3] = simplify_lookup[mem8[3]]; + mem8[4] = simplify_lookup[mem8[4]]; + mem8[5] = simplify_lookup[mem8[5]]; + mem8[6] = simplify_lookup[mem8[6]]; + mem8[7] = simplify_lookup[mem8[7]]; + + } else *mem = 0x0101010101010101ULL; + + mem++; + + } + +} + +#else + +static void simplify_trace(u32* mem) { + + u32 i = MAP_SIZE >> 2; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u8* mem8 = (u8*)mem; + + mem8[0] = simplify_lookup[mem8[0]]; + mem8[1] = simplify_lookup[mem8[1]]; + mem8[2] = simplify_lookup[mem8[2]]; + mem8[3] = simplify_lookup[mem8[3]]; + + } else *mem = 0x01010101; + + mem++; + } + +} + +#endif /* ^__x86_64__ */ + + +/* Destructively classify execution counts in a trace. This is used as a + preprocessing step for any newly acquired traces. Called on every exec, + must be fast. */ + +static u8 count_class_lookup8[256] = {0}; + +static u16 count_class_lookup16[65536]; + +void memset_fucking_array(){ + simplify_lookup[0] = 1; + memset(simplify_lookup+1, 128, 255); + + count_class_lookup8[0] = 0; + count_class_lookup8[1] = 1; + count_class_lookup8[2] = 2; + count_class_lookup8[3] = 4; + memset(count_class_lookup8 + 4, 8, 7 - 4 + 1); + memset(count_class_lookup8 + 8, 16, 15 - 8 + 1); + memset(count_class_lookup8 + 16, 32, 32 - 16); + memset(count_class_lookup8 + 32, 64, 128 - 32); + memset(count_class_lookup8 + 128, 128, 128); +} + +EXP_ST void init_count_class16(void) { + + u32 b1, b2; + + for (b1 = 0; b1 < 256; b1++) + for (b2 = 0; b2 < 256; b2++) + count_class_lookup16[(b1 << 8) + b2] = + (count_class_lookup8[b1] << 8) | + count_class_lookup8[b2]; + +} + + +#ifdef __x86_64__ + +static inline void classify_counts(u64* mem) { + + u32 i = MAP_SIZE >> 3; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u16* mem16 = (u16*)mem; + + mem16[0] = count_class_lookup16[mem16[0]]; + mem16[1] = count_class_lookup16[mem16[1]]; + mem16[2] = count_class_lookup16[mem16[2]]; + mem16[3] = count_class_lookup16[mem16[3]]; + + } + + mem++; + + } + +} + +#else + +static inline void classify_counts(u32* mem) { + + u32 i = MAP_SIZE >> 2; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u16* mem16 = (u16*)mem; + + mem16[0] = count_class_lookup16[mem16[0]]; + mem16[1] = count_class_lookup16[mem16[1]]; + + } + + mem++; + + } + +} + +#endif /* ^__x86_64__ */ + + +/* Get rid of shared memory (atexit handler). */ + +static void remove_shm(void) { + + shmctl(shm_id, IPC_RMID, NULL); + +} + + +/* Compact trace bytes into a smaller bitmap. We effectively just drop the + count information here. This is called only sporadically, for some + new paths. */ + +static void minimize_bits(u8* dst, u8* src) { + + u32 i = 0; + + while (i < MAP_SIZE) { + + if (*(src++)) dst[i >> 3] |= 1 << (i & 7); + i++; + + } + +} + + +/* When we bump into a new path, we call this to see if the path appears + more "favorable" than any of the existing ones. The purpose of the + "favorables" is to have a minimal set of paths that trigger all the bits + seen in the bitmap so far, and focus on fuzzing them at the expense of + the rest. + + The first step of the process is to maintain a list of top_rated[] entries + for every byte in the bitmap. We win that slot if there is no previous + contender, or if the contender has a more favorable speed x size factor. */ + +static void update_bitmap_score(struct queue_entry* q) { + + u32 i; + u64 fav_factor = q->exec_us * q->len; + + /* For every byte set in trace_bits[], see if there is a previous winner, + and how it compares to us. */ + + for (i = 0; i < MAP_SIZE; i++) + + if (trace_bits[i]) { + + if (top_rated[i]) { + + /* Faster-executing or smaller test cases are favored. */ + + if (fav_factor > top_rated[i]->exec_us * top_rated[i]->len) continue; + + /* Looks like we're going to win. Decrease ref count for the + previous winner, discard its trace_bits[] if necessary. */ + + if (!--top_rated[i]->tc_ref) { + ck_free(top_rated[i]->trace_mini); + top_rated[i]->trace_mini = 0; + } + + } + + /* Insert ourselves as the new winner. */ + + top_rated[i] = q; + q->tc_ref++; + + if (!q->trace_mini) { + q->trace_mini = ck_alloc(MAP_SIZE >> 3); + minimize_bits(q->trace_mini, trace_bits); + } + + score_changed = 1; + + } + +} + + +/* The second part of the mechanism discussed above is a routine that + goes over top_rated[] entries, and then sequentially grabs winners for + previously-unseen bytes (temp_v) and marks them as favored, at least + until the next run. The favored entries are given more air time during + all fuzzing steps. */ + +static void cull_queue(void) { + + struct queue_entry* q; + static u8 temp_v[MAP_SIZE >> 3]; + u32 i; + + if (dumb_mode || !score_changed) return; + + score_changed = 0; + + memset(temp_v, 255, MAP_SIZE >> 3); + + queued_favored = 0; + pending_favored = 0; + + q = queue; + + while (q) { + q->favored = 0; + q = q->next; + } + + /* Let's see if anything in the bitmap isn't captured in temp_v. + If yes, and if it has a top_rated[] contender, let's use it. */ + + for (i = 0; i < MAP_SIZE; i++) + if (top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { + + u32 j = MAP_SIZE >> 3; + + /* Remove all bits belonging to the current entry from temp_v. */ + + while (j--) + if (top_rated[i]->trace_mini[j]) + temp_v[j] &= ~top_rated[i]->trace_mini[j]; + + top_rated[i]->favored = 1; + queued_favored++; + + if (!top_rated[i]->was_fuzzed) pending_favored++; + + } + + q = queue; + + while (q) { + mark_as_redundant(q, !q->favored); + q = q->next; + } + +} + + +/* Configure shared memory and virgin_bits. This is called at startup. */ + +EXP_ST void setup_shm(void) { + + u8* shm_str; + + if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); + + memset(virgin_tmout, 255, MAP_SIZE); + memset(virgin_crash, 255, MAP_SIZE); + + shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); + + if (shm_id < 0) PFATAL("shmget() failed"); + + atexit(remove_shm); + + shm_str = alloc_printf("%d", shm_id); + + /* If somebody is asking us to fuzz instrumented binaries in dumb mode, + we don't want them to detect instrumentation, since we won't be sending + fork server commands. This should be replaced with better auto-detection + later on, perhaps? */ + + if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); + ck_free(shm_str); + trace_bits = shmat(shm_id, NULL, 0); + + if (!trace_bits) PFATAL("shmat() failed"); + +} + + +/* Load postprocessor, if available. */ + +static void setup_post(void) { + + void* dh; + u8* fn = getenv("AFL_POST_LIBRARY"); + u32 tlen = 6; + + if (!fn) return; + + ACTF("Loading postprocessor from '%s'...", fn); + + dh = dlopen(fn, RTLD_NOW); + if (!dh) FATAL("%s", dlerror()); + + post_handler = dlsym(dh, "afl_postprocess"); + if (!post_handler) FATAL("Symbol 'afl_postprocess' not found."); + + /* Do a quick test. It's better to segfault now than later =) */ + + post_handler("hello", &tlen); + + OKF("Postprocessor installed successfully."); + +} + + +/* Read all testcases from the input directory, then queue them for testing. + Called at startup. */ + +static void read_testcases(void) { + + struct dirent **nl; + s32 nl_cnt; + u32 i; + u8* fn; + + /* Auto-detect non-in-place resumption attempts. */ + + fn = alloc_printf("%s/queue", in_dir); + if (!access(fn, F_OK)) in_dir = fn; else ck_free(fn); + + ACTF("Scanning '%s'...", in_dir); + + /* We use scandir() + alphasort() rather than readdir() because otherwise, + the ordering of test cases would vary somewhat randomly and would be + difficult to control. */ + + nl_cnt = scandir(in_dir, &nl, NULL, alphasort); + + if (nl_cnt < 0) { + + if (errno == ENOENT || errno == ENOTDIR) + + SAYF("\n" cLRD "[-] " cRST + "The input directory does not seem to be valid - try again. The fuzzer needs\n" + " one or more test case to start with - ideally, a small file under 1 kB\n" + " or so. The cases must be stored as regular files directly in the input\n" + " directory.\n"); + + PFATAL("Unable to open '%s'", in_dir); + + } + + if (shuffle_queue && nl_cnt > 1) { + + ACTF("Shuffling queue..."); + shuffle_ptrs((void**)nl, nl_cnt); + + } + + for (i = 0; i < nl_cnt; i++) { + + struct stat st; + + u8* fn = alloc_printf("%s/%s", in_dir, nl[i]->d_name); + u8* dfn = alloc_printf("%s/.state/deterministic_done/%s", in_dir, nl[i]->d_name); + + u8 passed_det = 0; + + free(nl[i]); /* not tracked */ + + if (lstat(fn, &st) || access(fn, R_OK)) + PFATAL("Unable to access '%s'", fn); + + /* This also takes care of . and .. */ + + if (!S_ISREG(st.st_mode) || !st.st_size || strstr((char *)fn, "/README.txt")) { + + ck_free(fn); + ck_free(dfn); + continue; + + } + + if (st.st_size > MAX_FILE) + FATAL("Test case '%s' is too big (%s, limit is %s)", fn, + DMS(st.st_size), DMS(MAX_FILE)); + + /* Check for metadata that indicates that deterministic fuzzing + is complete for this entry. We don't want to repeat deterministic + fuzzing when resuming aborted scans, because it would be pointless + and probably very time-consuming. */ + + if (!access(dfn, F_OK)) passed_det = 1; + ck_free(dfn); + + add_to_queue(fn, st.st_size, passed_det); + + } + + free(nl); /* not tracked */ + + if (!queued_paths) { + + SAYF("\n" cLRD "[-] " cRST + "Looks like there are no valid test cases in the input directory! The fuzzer\n" + " needs one or more test case to start with - ideally, a small file under\n" + " 1 kB or so. The cases must be stored as regular files directly in the\n" + " input directory.\n"); + + FATAL("No usable test cases in '%s'", in_dir); + + } + + last_path_time = 0; + queued_at_start = queued_paths; + +} + + +/* Helper function for load_extras. */ + +static int compare_extras_len(const void* p1, const void* p2) { + struct extra_data *e1 = (struct extra_data*)p1, + *e2 = (struct extra_data*)p2; + + return e1->len - e2->len; +} + +static int compare_extras_use_d(const void* p1, const void* p2) { + struct extra_data *e1 = (struct extra_data*)p1, + *e2 = (struct extra_data*)p2; + + return e2->hit_cnt - e1->hit_cnt; +} + + +/* Read extras from a file, sort by size. */ + +static void load_extras_file(u8* fname, u32* min_len, u32* max_len, + u32 dict_level) { + + FILE* f; + u8 buf[MAX_LINE]; + u8 *lptr; + u32 cur_line = 0; + + f = fopen(fname, "r"); + + if (!f) PFATAL("Unable to open '%s'", fname); + + while ((lptr = fgets(buf, MAX_LINE, f))) { + + u8 *rptr, *wptr; + u32 klen = 0; + + cur_line++; + + /* Trim on left and right. */ + + while (isspace(*lptr)) lptr++; + + rptr = lptr + strlen(lptr) - 1; + while (rptr >= lptr && isspace(*rptr)) rptr--; + rptr++; + *rptr = 0; + + /* Skip empty lines and comments. */ + + if (!*lptr || *lptr == '#') continue; + + /* All other lines must end with '"', which we can consume. */ + + rptr--; + + if (rptr < lptr || *rptr != '"') + FATAL("Malformed name=\"value\" pair in line %u.", cur_line); + + *rptr = 0; + + /* Skip alphanumerics and dashes (label). */ + + while (isalnum(*lptr) || *lptr == '_') lptr++; + + /* If @number follows, parse that. */ + + if (*lptr == '@') { + + lptr++; + if (atoi(lptr) > dict_level) continue; + while (isdigit(*lptr)) lptr++; + + } + + /* Skip whitespace and = signs. */ + + while (isspace(*lptr) || *lptr == '=') lptr++; + + /* Consume opening '"'. */ + + if (*lptr != '"') + FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); + + lptr++; + + if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); + + /* Okay, let's allocate memory and copy data between "...", handling + \xNN escaping, \\, and \". */ + + extras = ck_realloc_block(extras, (extras_cnt + 1) * + sizeof(struct extra_data)); + + wptr = extras[extras_cnt].data = ck_alloc(rptr - lptr); + + while (*lptr) { + + char* hexdigits = "0123456789abcdef"; + + switch (*lptr) { + + case 1 ... 31: + case 128 ... 255: + FATAL("Non-printable characters in line %u.", cur_line); + + case '\\': + + lptr++; + + if (*lptr == '\\' || *lptr == '"') { + *(wptr++) = *(lptr++); + klen++; + break; + } + + if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) + FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); + + *(wptr++) = + ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) | + (strchr(hexdigits, tolower(lptr[2])) - hexdigits); + + lptr += 3; + klen++; + + break; + + default: + + *(wptr++) = *(lptr++); + klen++; + + } + + } + + extras[extras_cnt].len = klen; + + if (extras[extras_cnt].len > MAX_DICT_FILE) + FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, + DMS(klen), DMS(MAX_DICT_FILE)); + + if (*min_len > klen) *min_len = klen; + if (*max_len < klen) *max_len = klen; + + extras_cnt++; + + } + + fclose(f); + +} + + +/* Read extras from the extras directory and sort them by size. */ + +static void load_extras(u8* dir) { + + DIR* d; + struct dirent* de; + u32 min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0; + u8* x; + + /* If the name ends with @, extract level and continue. */ + + if ((x = strchr((char *)dir, '@'))) { + + *x = 0; + dict_level = atoi(x + 1); + + } + + ACTF("Loading extra dictionary from '%s' (level %u)...", dir, dict_level); + + d = opendir(dir); + + if (!d) { + + if (errno == ENOTDIR) { + load_extras_file(dir, &min_len, &max_len, dict_level); + goto check_and_sort; + } + + PFATAL("Unable to open '%s'", dir); + + } + + if (x) FATAL("Dictionary levels not supported for directories."); + + while ((de = readdir(d))) { + + struct stat st; + u8* fn = alloc_printf("%s/%s", dir, de->d_name); + s32 fd; + + if (lstat(fn, &st) || access(fn, R_OK)) + PFATAL("Unable to access '%s'", fn); + + /* This also takes care of . and .. */ + if (!S_ISREG(st.st_mode) || !st.st_size) { + + ck_free(fn); + continue; + + } + + if (st.st_size > MAX_DICT_FILE) + FATAL("Extra '%s' is too big (%s, limit is %s)", fn, + DMS(st.st_size), DMS(MAX_DICT_FILE)); + + if (min_len > st.st_size) min_len = st.st_size; + if (max_len < st.st_size) max_len = st.st_size; + + extras = ck_realloc_block(extras, (extras_cnt + 1) * + sizeof(struct extra_data)); + + extras[extras_cnt].data = ck_alloc(st.st_size); + extras[extras_cnt].len = st.st_size; + + fd = open(fn, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", fn); + + ck_read(fd, extras[extras_cnt].data, st.st_size, fn); + + close(fd); + ck_free(fn); + + extras_cnt++; + + } + + closedir(d); + +check_and_sort: + + if (!extras_cnt) FATAL("No usable files in '%s'", dir); + + qsort(extras, extras_cnt, sizeof(struct extra_data), compare_extras_len); + + OKF("Loaded %u extra tokens, size range %s to %s.", extras_cnt, + DMS(min_len), DMS(max_len)); + + if (max_len > 32) + WARNF("Some tokens are relatively large (%s) - consider trimming.", + DMS(max_len)); + + if (extras_cnt > MAX_DET_EXTRAS) + WARNF("More than %u tokens - will use them probabilistically.", + MAX_DET_EXTRAS); + +} + + + + +/* Helper function for maybe_add_auto() */ + +static inline u8 memcmp_nocase(u8* m1, u8* m2, u32 len) { + + while (len--) if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1; + return 0; + +} + + +/* Maybe add automatic extra. */ + +static void maybe_add_auto(u8* mem, u32 len) { + + u32 i; + + /* Allow users to specify that they don't want auto dictionaries. */ + + if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return; + + /* Skip runs of identical bytes. */ + + for (i = 1; i < len; i++) + if (mem[0] ^ mem[i]) break; + + if (i == len) return; + + /* Reject builtin interesting values. */ + + if (len == 2) { + + i = sizeof(interesting_16) >> 1; + + while (i--) + if (*((u16*)mem) == interesting_16[i] || + *((u16*)mem) == SWAP16(interesting_16[i])) return; + + } + + if (len == 4) { + + i = sizeof(interesting_32) >> 2; + + while (i--) + if (*((u32*)mem) == interesting_32[i] || + *((u32*)mem) == SWAP32(interesting_32[i])) return; + + } + + /* Reject anything that matches existing extras. Do a case-insensitive + match. We optimize by exploiting the fact that extras[] are sorted + by size. */ + + for (i = 0; i < extras_cnt; i++) + if (extras[i].len >= len) break; + + for (; i < extras_cnt && extras[i].len == len; i++) + if (!memcmp_nocase(extras[i].data, mem, len)) return; + + /* Last but not least, check a_extras[] for matches. There are no + guarantees of a particular sort order. */ + + auto_changed = 1; + + for (i = 0; i < a_extras_cnt; i++) { + + if (a_extras[i].len == len && !memcmp_nocase(a_extras[i].data, mem, len)) { + + a_extras[i].hit_cnt++; + goto sort_a_extras; + + } + + } + + /* At this point, looks like we're dealing with a new entry. So, let's + append it if we have room. Otherwise, let's randomly evict some other + entry from the bottom half of the list. */ + + if (a_extras_cnt < MAX_AUTO_EXTRAS) { + + a_extras = ck_realloc_block(a_extras, (a_extras_cnt + 1) * + sizeof(struct extra_data)); + + a_extras[a_extras_cnt].data = ck_memdup(mem, len); + a_extras[a_extras_cnt].len = len; + a_extras_cnt++; + + } else { + + i = MAX_AUTO_EXTRAS / 2 + + UR((MAX_AUTO_EXTRAS + 1) / 2); + + ck_free(a_extras[i].data); + + a_extras[i].data = ck_memdup(mem, len); + a_extras[i].len = len; + a_extras[i].hit_cnt = 0; + + } + +sort_a_extras: + + /* First, sort all auto extras by use count, descending order. */ + + qsort(a_extras, a_extras_cnt, sizeof(struct extra_data), + compare_extras_use_d); + + /* Then, sort the top USE_AUTO_EXTRAS entries by size. */ + + qsort(a_extras, MIN(USE_AUTO_EXTRAS, a_extras_cnt), + sizeof(struct extra_data), compare_extras_len); + +} + + +/* Save automatically generated extras. */ + +static void save_auto(void) { + + u32 i; + + if (!auto_changed) return; + auto_changed = 0; + + for (i = 0; i < MIN(USE_AUTO_EXTRAS, a_extras_cnt); i++) { + + u8* fn = alloc_printf("%s/queue/.state/auto_extras/auto_%06u", out_dir, i); + s32 fd; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_write(fd, a_extras[i].data, a_extras[i].len, fn); + + close(fd); + ck_free(fn); + + } + +} + + +/* Load automatically generated extras. */ + +static void load_auto(void) { + + u32 i; + + for (i = 0; i < USE_AUTO_EXTRAS; i++) { + + u8 tmp[MAX_AUTO_EXTRA + 1]; + u8* fn = alloc_printf("%s/.state/auto_extras/auto_%06u", in_dir, i); + s32 fd, len; + + fd = open(fn, O_RDONLY, 0600); + + if (fd < 0) { + + if (errno != ENOENT) PFATAL("Unable to open '%s'", fn); + ck_free(fn); + break; + + } + + /* We read one byte more to cheaply detect tokens that are too + long (and skip them). */ + + len = read(fd, tmp, MAX_AUTO_EXTRA + 1); + + if (len < 0) PFATAL("Unable to read from '%s'", fn); + + if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) + maybe_add_auto(tmp, len); + + close(fd); + ck_free(fn); + + } + + if (i) OKF("Loaded %u auto-discovered dictionary tokens.", i); + else OKF("No auto-generated dictionary tokens to reuse."); + +} + + +/* Destroy extras. */ + +static void destroy_extras(void) { + + u32 i; + + for (i = 0; i < extras_cnt; i++) + ck_free(extras[i].data); + + ck_free(extras); + + for (i = 0; i < a_extras_cnt; i++) + ck_free(a_extras[i].data); + + ck_free(a_extras); + +} + + +/* Spin up fork server (instrumented mode only). The idea is explained here: + + http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html + + In essence, the instrumentation allows us to skip execve(), and just keep + cloning a stopped child. So, we just execute once, and then send commands + through a pipe. The other part of this logic is in afl-as.h. */ + +EXP_ST void init_forkserver(char** argv) { + + static struct itimerval it; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; + ACTF("Spinning up the fork server..."); + + if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); + + forksrv_pid = fork(); + + if (forksrv_pid < 0) PFATAL("fork() failed"); + + if (!forksrv_pid) { + + struct rlimit r; + + /* Umpf. On OpenBSD, the default fd limit for root users is set to + soft 128. Let's try to fix that... */ + + if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) { + + r.rlim_cur = FORKSRV_FD + 2; + setrlimit(RLIMIT_NOFILE, &r); /* Ignore errors */ + + } + + if (mem_limit) { + + r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 50; + +#ifdef RLIMIT_AS + + setrlimit(RLIMIT_AS, &r); /* Ignore errors */ + +#else + + /* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but + according to reliable sources, RLIMIT_DATA covers anonymous + maps - so we should be getting good protection against OOM bugs. */ + + setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ + +#endif /* ^RLIMIT_AS */ + + + } + + /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered + before the dump is complete. */ + + r.rlim_max = r.rlim_cur = 0; + + setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + + /* Isolate the process and configure standard descriptors. If out_file is + specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ + + setsid(); + + dup2(dev_null_fd, 1); + dup2(dev_null_fd, 2); + + if (out_file) { + + dup2(dev_null_fd, 0); + + } else { + + dup2(out_fd, 0); + close(out_fd); + + } + + /* Set up control and status pipes, close the unneeded original fds. */ + + if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); + if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed"); + + close(ctl_pipe[0]); + close(ctl_pipe[1]); + close(st_pipe[0]); + close(st_pipe[1]); + + close(out_dir_fd); + close(dev_null_fd); + close(dev_urandom_fd); + close(fileno(plot_file)); + + /* This should improve performance a bit, since it stops the linker from + doing extra work post-fork(). */ + + if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); + + /* Set sane defaults for ASAN if nothing else specified. */ + + setenv("ASAN_OPTIONS", "abort_on_error=1:" + "detect_leaks=0:" + "symbolize=0:" + "allocator_may_return_null=1", 0); + + /* MSAN is tricky, because it doesn't support abort_on_error=1 at this + point. So, we do this in a very hacky way. */ + + setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" + "symbolize=0:" + "abort_on_error=1:" + "allocator_may_return_null=1:" + "msan_track_origins=0", 0); + + /* char * tmp_target_path = "/usr/local/mysql/bin/mysqld"; + char * tmp_argv[] = {"/usr/local/mysql/bin/mysqld", + "--basedir=/usr/local/mysql", + "--datadir=/usr/local/mysql/data", + "--plugin-dir=/usr/local/mysql/lib/plugin", + "--user=mysql", + "--log-error=lrs-dwu01.err", + "--pid-file=lrs-dwu01.pid", + "--socket=/tmp/mysql.sock", + NULL}; + execv(tmp_target_path, tmp_argv); //改参数把,别改这里了,我再去看看那个启动参数 +*/ + /* Use a distinctive bitmap signature to tell the parent about execv() + falling through. */ + + *(u32*)trace_bits = EXEC_FAIL_SIG; + exit(0); + + } + + /* Close the unneeded endpoints. */ + + close(ctl_pipe[0]); + close(st_pipe[1]); + + fsrv_ctl_fd = ctl_pipe[1]; + fsrv_st_fd = st_pipe[0]; + + + /* Wait for the fork server to come up, but don't wait too long. */ + + it.it_value.tv_sec = ((exec_tmout * FORK_WAIT_MULT) / 1000); + it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + + setitimer(ITIMER_REAL, &it, NULL); + + rlen = read(fsrv_st_fd, &status, 4); + child_pid = status; + assert(child_pid != -1); + + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &it, NULL); + + /* If we have a four-byte "hello" message from the server, we're all set. + Otherwise, try to figure out what went wrong. */ + + if (rlen == 4) { + OKF("All right - fork server is up."); + return; + } + + if (child_timed_out) + FATAL("Timeout while initializing fork server (adjusting -t may help)"); + + if (waitpid(forksrv_pid, &status, 0) <= 0) + PFATAL("waitpid() failed"); + + if (WIFSIGNALED(status)) { + + if (mem_limit && mem_limit < 500 && uses_asan) { + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the target binary crashed suddenly, before receiving any input\n" + " from the fuzzer! Since it seems to be built with ASAN and you have a\n" + " restrictive memory limit configured, this is expected; please read\n" + " %s/notes_for_asan.txt for help.\n", doc_path); + + } else if (!mem_limit) { + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the target binary crashed suddenly, before receiving any input\n" + " from the fuzzer! There are several probable explanations:\n\n" + + " - The binary is just buggy and explodes entirely on its own. If so, you\n" + " need to fix the underlying problem or find a better replacement.\n\n" + +#ifdef __APPLE__ + + " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" + " break afl-fuzz performance optimizations when running platform-specific\n" + " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" + +#endif /* __APPLE__ */ + + " - Less likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n"); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the target binary crashed suddenly, before receiving any input\n" + " from the fuzzer! There are several probable explanations:\n\n" + + " - The current memory limit (%s) is too restrictive, causing the\n" + " target to hit an OOM condition in the dynamic linker. Try bumping up\n" + " the limit with the -m setting in the command line. A simple way confirm\n" + " this diagnosis would be:\n\n" + +#ifdef RLIMIT_AS + " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#else + " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#endif /* ^RLIMIT_AS */ + + " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" + " estimate the required amount of virtual memory for the binary.\n\n" + + " - The binary is just buggy and explodes entirely on its own. If so, you\n" + " need to fix the underlying problem or find a better replacement.\n\n" + +#ifdef __APPLE__ + + " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" + " break afl-fuzz performance optimizations when running platform-specific\n" + " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" + +#endif /* __APPLE__ */ + + " - Less likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n", + DMS(mem_limit << 20), mem_limit - 1); + + } + + FATAL("Fork server crashed with signal %d", WTERMSIG(status)); + + } + + if (*(u32*)trace_bits == EXEC_FAIL_SIG) + FATAL("Unable to execute target application ('%s')", argv[0]); + + if (mem_limit && mem_limit < 500 && uses_asan) { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, looks like the target binary terminated before we could complete a\n" + " handshake with the injected code. Since it seems to be built with ASAN and\n" + " you have a restrictive memory limit configured, this is expected; please\n" + " read %s/notes_for_asan.txt for help.\n", doc_path); + + } else if (!mem_limit) { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, looks like the target binary terminated before we could complete a\n" + " handshake with the injected code. Perhaps there is a horrible bug in the\n" + " fuzzer. Poke for troubleshooting tips.\n"); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, looks like the target binary terminated before we could complete a\n" + " handshake with the injected code. There are %s probable explanations:\n\n" + + "%s" + " - The current memory limit (%s) is too restrictive, causing an OOM\n" + " fault in the dynamic linker. This can be fixed with the -m option. A\n" + " simple way to confirm the diagnosis may be:\n\n" + +#ifdef RLIMIT_AS + " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#else + " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#endif /* ^RLIMIT_AS */ + + " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" + " estimate the required amount of virtual memory for the binary.\n\n" + + " - Less likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n", + getenv(DEFER_ENV_VAR) ? "three" : "two", + getenv(DEFER_ENV_VAR) ? + " - You are using deferred forkserver, but __AFL_INIT() is never\n" + " reached before the program terminates.\n\n" : "", + DMS(mem_limit << 20), mem_limit - 1); + + } + + FATAL("Fork server handshake failed"); + +} + +/* Execute target application, monitoring for timeouts. Return status + information. The called program will update trace_bits[]. */ + +int counter; +static u8 run_target(char** argv, u32 timeout) { + + static struct itimerval it; + static u32 prev_timed_out = 0; + static u64 exec_ms = 0; + int status = 0; + u32 tb4; + + child_timed_out = 0; + + /* After this memset, trace_bits[] are effectively volatile, so we + must prevent any earlier operations from venturing into that + territory. */ + + memset(trace_bits, 0, MAP_SIZE); + MEM_BARRIER(); + +//********************************** + + vaild_flag = 0; + + SQLSTATUS result = g_connector.execute(g_current_sql); + + if (result == SQLSTATUS::ssConnectFailed) { + while (1) { + sleep(0.1); + + g_connector.start_db(file, options); + result = g_connector.execute(g_current_sql); + + if ((result != SQLSTATUS::ssConnectFailed) || stop_soon) { + break; + } + } + } + + if(result == SQLSTATUS::ssServerCrash){ + status = FAULT_CRASH; + }else{ + if(result == SQLSTATUS::ssNormal){ + vaild_flag = 1; + total_vaild++; + } + + status = FAULT_NONE; + } + + total_execs++; + cur_execs++; + +//********************************** + + MEM_BARRIER(); + + tb4 = *(u32*)trace_bits; + +#ifdef __x86_64__ + classify_counts((u64*)trace_bits); +#else + classify_counts((u32*)trace_bits); +#endif /* ^__x86_64__ */ + + return status; +} + + +/* Write modified data to file for testing. If out_file is set, the old file + is unlinked and a new one is created. Otherwise, out_fd is rewound and + truncated. */ + +static void write_to_testcase(void* mem, u32 len) { + + g_current_sql = (char *)mem; + return ; + +} + + +/* The same, but with an adjustable gap. Used for trimming. */ + +static void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) { + + s32 fd = out_fd; + u32 tail_len = len - skip_at - skip_len; + + if (out_file) { + + unlink(out_file); /* Ignore errors. */ + + fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", out_file); + + } else lseek(fd, 0, SEEK_SET); + + if (skip_at) ck_write(fd, mem, skip_at, out_file); + + if (tail_len) ck_write(fd, mem + skip_at + skip_len, tail_len, out_file); + + if (!out_file) { + + if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed"); + lseek(fd, 0, SEEK_SET); + + } else close(fd); + +} + + +static void show_stats(void); + +/* Calibrate a new test case. This is done when processing the input directory + to warn about flaky or otherwise problematic test cases early on; and when + new paths are discovered to detect variable behavior and so on. */ + +static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem, + u32 handicap, u8 from_queue) { + + static u8 first_trace[MAP_SIZE]; + + u8 fault = 0, new_bits = 0, var_detected = 0, + first_run = (q->exec_cksum == 0); + + u64 start_us, stop_us; + + s32 old_sc = stage_cur, old_sm = stage_max; + u32 use_tmout = exec_tmout; + u8* old_sn = stage_name; + + /* Be a bit more generous about timeouts when resuming sessions, or when + trying to calibrate already-added finds. This helps avoid trouble due + to intermittent latency. */ + + if (!from_queue || resuming_fuzz) + use_tmout = MAX(exec_tmout + CAL_TMOUT_ADD, + exec_tmout * CAL_TMOUT_PERC / 100); + + q->cal_failed++; + + stage_name = "calibration"; + stage_max = fast_cal ? 3 : CAL_CYCLES; + + /* Make sure the forkserver is up before we do anything, and let's not + count its spin-up time toward binary calibration. */ + + if (dumb_mode != 1 && !no_forkserver && !forksrv_pid){ + /* + int idx = 0; + cout << "Init fork server arguments: " << endl; + while(auto s = argv[idx]){ + cout << argv[idx++] << endl; + } + cin >> idx; + */ + //init_forkserver(argv); + } + + + if (q->exec_cksum) memcpy(first_trace, trace_bits, MAP_SIZE); + + start_us = get_cur_time_us(); + + for (stage_cur = 0; stage_cur < 1; stage_cur++) { + + u32 cksum; + + if (!first_run && !(stage_cur % stats_update_freq)) show_stats(); + + write_to_testcase(use_mem, q->len); + + fault = run_target(argv, use_tmout); + + /* stop_soon is set by the handler for Ctrl+C. When it's pressed, + we want to bail out quickly. */ + + if (stop_soon || fault != crash_mode) goto abort_calibration; + + if (!dumb_mode && !stage_cur && !count_bytes(trace_bits)) { + fault = FAULT_NOINST; + goto abort_calibration; + } + + cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + + if (q->exec_cksum != cksum) { + + u8 hnb = has_new_bits(virgin_bits); + if (hnb > new_bits) new_bits = hnb; + + if (q->exec_cksum) { + + u32 i; + + for (i = 0; i < MAP_SIZE; i++) { + + if (!var_bytes[i] && first_trace[i] != trace_bits[i]) { + + var_bytes[i] = 1; + virgin_bits[i] = 0; + stage_max = CAL_CYCLES_LONG; + + } + + } + + var_detected = 1; + + } else { + + q->exec_cksum = cksum; + memcpy(first_trace, trace_bits, MAP_SIZE); + + } + + } + + } + + stop_us = get_cur_time_us(); + + total_cal_us += stop_us - start_us; + total_cal_cycles += stage_max; + + /* OK, let's collect some stats about the performance of this test case. + This is used for fuzzing air time calculations in calculate_score(). */ + + q->exec_us = (stop_us - start_us) / stage_max; + q->bitmap_size = count_bytes(trace_bits); + q->handicap = handicap; + q->cal_failed = 0; + + total_bitmap_size += q->bitmap_size; + total_bitmap_entries++; + + update_bitmap_score(q); + + /* If this case didn't result in new output from the instrumentation, tell + parent. This is a non-critical problem, but something to warn the user + about. */ + + if (!dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS; + +abort_calibration: + + if (new_bits == 2 && !q->has_new_cov) { + q->has_new_cov = 1; + queued_with_cov++; + } + + /* Mark variable paths. */ + + if (var_detected) { + + var_byte_count = count_bytes(var_bytes); + + if (!q->var_behavior) { + mark_as_variable(q); + queued_variable++; + } + + } + + stage_name = old_sn; + stage_cur = old_sc; + stage_max = old_sm; + + if (!first_run) show_stats(); + + return fault; + +} + + +/* Examine map coverage. Called once, for first test case. */ + +static void check_map_coverage(void) { + + u32 i; + + if (count_bytes(trace_bits) < 100) return; + + for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; i++) + if (trace_bits[i]) return; + + WARNF("Recompile binary with newer version of afl to improve coverage!"); + +} + + +/* Perform dry run of all test cases to confirm that the app is working as + expected. This is done only for the initial inputs, and only once. */ + +static void perform_dry_run(char** argv) { + + struct queue_entry* q = queue; + u32 cal_failures = 0; + u8* skip_crashes = getenv("AFL_SKIP_CRASHES"); + + while (q) { + + u8* use_mem; + u8 res; + s32 fd; + + u8* fn = strrchr((char *)q->fname, '/') + 1; + + ACTF("Attempting dry run with '%s'...", fn); + + fd = open(q->fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", q->fname); + + use_mem = (u8*)malloc(q->len + 1); + + if (read(fd, use_mem, q->len) != q->len) + FATAL("Short read from '%s'", q->fname); + + close(fd); + +//********************************* + + use_mem[q->len] = '\0'; + + IR* root = g_mutator.IR_parser(use_mem); + free(use_mem); + + if (root == nullptr) { + q = q->next; + continue; + } + + string ir_str = root->to_string(); + + char* tmp_str = ir_str.c_str(); + int siz = ir_str.size(); + + q->len = siz; + + res = calibrate_case(argv, q, tmp_str, 0, 1); + + if (stop_soon) return; + + //********************************* + + if (res == crash_mode || res == FAULT_NOBITS) + SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, + q->len, q->bitmap_size, q->exec_us); + + switch (res) { + + case FAULT_NONE: + + if (q == queue) check_map_coverage(); + + if (crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); + + break; + + case FAULT_TMOUT: + + if (timeout_given) { + + /* The -t nn+ syntax in the command line sets timeout_given to '2' and + instructs afl-fuzz to tolerate but skip queue entries that time + out. */ + + if (timeout_given > 1) { + WARNF("Test case results in a timeout (skipping)"); + q->cal_failed = CAL_CHANCES; + cal_failures++; + break; + } + + SAYF("\n" cLRD "[-] " cRST + "The program took more than %u ms to process one of the initial test cases.\n" + " Usually, the right thing to do is to relax the -t option - or to delete it\n" + " altogether and allow the fuzzer to auto-calibrate. That said, if you know\n" + " what you are doing and want to simply skip the unruly test cases, append\n" + " '+' at the end of the value passed to -t ('-t %u+').\n", exec_tmout, + exec_tmout); + + FATAL("Test case '%s' results in a timeout", fn); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "The program took more than %u ms to process one of the initial test cases.\n" + " This is bad news; raising the limit with the -t option is possible, but\n" + " will probably make the fuzzing process extremely slow.\n\n" + + " If this test case is just a fluke, the other option is to just avoid it\n" + " altogether, and find one that is less of a CPU hog.\n", exec_tmout); + + FATAL("Test case '%s' results in a timeout", fn); + + } + + case FAULT_CRASH: + + if (crash_mode) break; + + if (skip_crashes) { + WARNF("Test case results in a crash (skipping)"); + q->cal_failed = CAL_CHANCES; + cal_failures++; + break; + } + + if (mem_limit) { + + SAYF("\n" cLRD "[-] " cRST + "Oops, the program crashed with one of the test cases provided. There are\n" + " several possible explanations:\n\n" + + " - The test case causes known crashes under normal working conditions. If\n" + " so, please remove it. The fuzzer should be seeded with interesting\n" + " inputs - but not ones that cause an outright crash.\n\n" + + " - The current memory limit (%s) is too low for this program, causing\n" + " it to die due to OOM when parsing valid files. To fix this, try\n" + " bumping it up with the -m setting in the command line. If in doubt,\n" + " try something along the lines of:\n\n" + +#ifdef RLIMIT_AS + " ( ulimit -Sv $[%llu << 10]; /path/to/binary [...] for troubleshooting tips.\n", + DMS(mem_limit << 20), mem_limit - 1, doc_path); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "Oops, the program crashed with one of the test cases provided. There are\n" + " several possible explanations:\n\n" + + " - The test case causes known crashes under normal working conditions. If\n" + " so, please remove it. The fuzzer should be seeded with interesting\n" + " inputs - but not ones that cause an outright crash.\n\n" + +#ifdef __APPLE__ + + " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" + " break afl-fuzz performance optimizations when running platform-specific\n" + " binaries. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" + +#endif /* __APPLE__ */ + + " - Least likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n"); + + } + + FATAL("Test case '%s' results in a crash", fn); + + case FAULT_ERROR: + + FATAL("Unable to execute target application ('%s')", argv[0]); + + case FAULT_NOINST: + + FATAL("No instrumentation detected"); + + case FAULT_NOBITS: + + useless_at_start++; + + if (!in_bitmap && !shuffle_queue) + WARNF("No new instrumentation output, test case may be useless."); + + break; + + } + + if (q->var_behavior) WARNF("Instrumentation output varies across runs."); + + deep_delete(root); + + q = q->next; + + } + + if (cal_failures) { + + if (cal_failures == queued_paths) + FATAL("All test cases time out%s, giving up!", + skip_crashes ? " or crash" : ""); + + WARNF("Skipped %u test cases (%0.02f%%) due to timeouts%s.", cal_failures, + ((double)cal_failures) * 100 / queued_paths, + skip_crashes ? " or crashes" : ""); + + if (cal_failures * 5 > queued_paths) + WARNF(cLRD "High percentage of rejected test cases, check settings!"); + + } + + OKF("All test cases processed."); + +} + + +/* Helper function: link() if possible, copy otherwise. */ + +static void link_or_copy(u8* old_path, u8* new_path) { + + s32 i = link(old_path, new_path); + s32 sfd, dfd; + u8* tmp; + + if (!i) return; + + sfd = open(old_path, O_RDONLY); + if (sfd < 0) PFATAL("Unable to open '%s'", old_path); + + dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (dfd < 0) PFATAL("Unable to create '%s'", new_path); + + tmp = ck_alloc(64 * 1024); + + while ((i = read(sfd, tmp, 64 * 1024)) > 0) + ck_write(dfd, tmp, i, new_path); + + if (i < 0) PFATAL("read() failed"); + + ck_free(tmp); + close(sfd); + close(dfd); + +} + + +static void nuke_resume_dir(void); + +/* Create hard links for input test cases in the output directory, choosing + good names and pivoting accordingly. */ + +static void pivot_inputs(void) { + + struct queue_entry* q = queue; + u32 id = 0; + + ACTF("Creating hard links for all input files..."); + + while (q) { + + u8 *nfn, *rsl = strrchr((const char*)q->fname, '/'); + u32 orig_id; + + if (!rsl) rsl = q->fname; else rsl++; + + /* If the original file name conforms to the syntax and the recorded + ID matches the one we'd assign, just use the original file name. + This is valuable for resuming fuzzing runs. */ + +#ifndef SIMPLE_FILES +# define CASE_PREFIX "id:" +#else +# define CASE_PREFIX "id_" +#endif /* ^!SIMPLE_FILES */ + + if (!strncmp(rsl, CASE_PREFIX, 3) && + sscanf(rsl + 3, "%06u", &orig_id) == 1 && orig_id == id) { + + u8* src_str; + u32 src_id; + + resuming_fuzz = 1; + nfn = alloc_printf("%s/queue/%s", out_dir, rsl); + + /* Since we're at it, let's also try to find parent and figure out the + appropriate depth for this entry. */ + + src_str = strchr((char *)(rsl + 3), ':'); + + if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { + + struct queue_entry* s = queue; + while (src_id-- && s) s = s->next; + if (s) q->depth = s->depth + 1; + + if (max_depth < q->depth) max_depth = q->depth; + + } + + } else { + + /* No dice - invent a new name, capturing the original one as a + substring. */ + +#ifndef SIMPLE_FILES + + u8* use_name = strstr((const char*)rsl, ",orig:"); + + if (use_name) use_name += 6; else use_name = rsl; + nfn = alloc_printf("%s/queue/id:%06u,orig:%s", out_dir, id, use_name); + +#else + + nfn = alloc_printf("%s/queue/id_%06u", out_dir, id); + +#endif /* ^!SIMPLE_FILES */ + + } + + /* Pivot to the new queue entry. */ + + link_or_copy(q->fname, nfn); + ck_free(q->fname); + q->fname = nfn; + + /* Make sure that the passed_det value carries over, too. */ + + if (q->passed_det) mark_as_det_done(q); + + q = q->next; + id++; + + } + + if (in_place_resume) nuke_resume_dir(); + +} + + +#ifndef SIMPLE_FILES + +/* Construct a file name for a new test case, capturing the operation + that led to its discovery. Uses a static buffer. */ + +static u8* describe_op(u8 hnb) { + + static u8 ret[256]; + + if (syncing_party) { + + sprintf(ret, "sync:%s,src:%06u", syncing_party, syncing_case); + + } else { + + sprintf(ret, "src:%06u", current_entry); + + if (splicing_with >= 0) + sprintf(ret + strlen(ret), "+%06u", splicing_with); + + sprintf(ret + strlen(ret), ",op:%s", stage_short); + + if (stage_cur_byte >= 0) { + + sprintf(ret + strlen(ret), ",pos:%u", stage_cur_byte); + + if (stage_val_type != STAGE_VAL_NONE) + sprintf(ret + strlen(ret), ",val:%s%+d", + (stage_val_type == STAGE_VAL_BE) ? "be:" : "", + stage_cur_val); + + } else sprintf(ret + strlen(ret), ",rep:%u", stage_cur_val); + + } + + if (hnb == 2) strcat(ret, ",+cov"); + + return ret; + +} + +#endif /* !SIMPLE_FILES */ + + +/* Write a message accompanying the crash directory :-) */ + +static void write_crash_readme(void) { + + u8* fn = alloc_printf("%s/crashes/README.txt", out_dir); + s32 fd; + FILE* f; + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + ck_free(fn); + + /* Do not die on errors here - that would be impolite. */ + + if (fd < 0) return; + + f = fdopen(fd, "w"); + + if (!f) { + close(fd); + return; + } + + fprintf(f, "Command line used to find this crash:\n\n" + + "%s\n\n" + + "If you can't reproduce a bug outside of afl-fuzz, be sure to set the same\n" + "memory limit. The limit used for this fuzzing session was %s.\n\n" + + "Need a tool to minimize test cases before investigating the crashes or sending\n" + "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n" + + "Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop\n" + "me a mail at once the issues are fixed - I'd love to\n" + "add your finds to the gallery at:\n\n" + + " http://lcamtuf.coredump.cx/afl/\n\n" + + "Thanks :-)\n", + + orig_cmdline, DMS(mem_limit << 20)); /* ignore errors */ + + fclose(f); + +} + + +/* Check if the result of an execve() during routine fuzzing is interesting, + save or queue the input test case for further analysis if so. Returns 1 if + entry is saved, 0 otherwise. */ + +static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) { + + u8 *fn = ""; + u8 hnb; + s32 fd; + u8 keeping = 0, res; + + if (fault == crash_mode) { + + /* Keep only if there are new bits in the map, add to queue for + future fuzzing, etc. */ + + if (!(hnb = has_new_bits(virgin_bits))) { + if (crash_mode) total_crashes++; + return 0; + } + + keeping = hnb; + + if(!vaild_flag) { + goto error_check; + } + +#ifndef SIMPLE_FILES + + fn = alloc_printf("%s/queue/id:%06u,%s", out_dir, queued_paths, + describe_op(hnb)); + +#else + + fn = alloc_printf("%s/queue/id_%06u", out_dir, queued_paths); + +#endif /* ^!SIMPLE_FILES */ + + add_to_queue(fn, len, 0); + + if (hnb == 2) { + queue_top->has_new_cov = 1; + queued_with_cov++; + } + + queue_top->exec_cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + + /* Try to calibrate inline; this also calls update_bitmap_score() when + successful. */ + + res = calibrate_case(argv, queue_top, mem, queue_cycle - 1, 0); + + if (res == FAULT_ERROR) + FATAL("Unable to execute target application"); + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_write(fd, mem, len, fn); + close(fd); + } + +error_check: + + switch (fault) { + + case FAULT_TMOUT: + + /* Timeouts are not very interesting, but we're still obliged to keep + a handful of samples. We use the presence of new bits in the + hang-specific bitmap as a signal of uniqueness. In "dumb" mode, we + just keep everything. */ + + total_tmouts++; + + if (unique_hangs >= KEEP_UNIQUE_HANG) return keeping; + + if (!dumb_mode) { + +#ifdef __x86_64__ + simplify_trace((u64*)trace_bits); +#else + simplify_trace((u32*)trace_bits); +#endif /* ^__x86_64__ */ + + if (!has_new_bits(virgin_tmout)) return keeping; + + } + + unique_tmouts++; + + /* Before saving, we make sure that it's a genuine hang by re-running + the target with a more generous timeout (unless the default timeout + is already generous). */ + + if (exec_tmout < hang_tmout) { + + u8 new_fault; + write_to_testcase(mem, len); + new_fault = run_target(argv, hang_tmout); + + /* A corner case that one user reported bumping into: increasing the + timeout actually uncovers a crash. Make sure we don't discard it if + so. */ + + if (!stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash; + + if (stop_soon || new_fault != FAULT_TMOUT) return keeping; + + } + +#ifndef SIMPLE_FILES + + fn = alloc_printf("%s/hangs/id:%06llu,%s", out_dir, + unique_hangs, describe_op(0)); + +#else + + fn = alloc_printf("%s/hangs/id_%06llu", out_dir, + unique_hangs); + +#endif /* ^!SIMPLE_FILES */ + + unique_hangs++; + + last_hang_time = get_cur_time(); + + break; + + case FAULT_CRASH: + +keep_as_crash: + + /* This is handled in a manner roughly similar to timeouts, + except for slightly different limits and no need to re-run test + cases. */ + + total_crashes++; + + if (unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; + + if (!dumb_mode) { + +#ifdef __x86_64__ + simplify_trace((u64*)trace_bits); +#else + simplify_trace((u32*)trace_bits); +#endif /* ^__x86_64__ */ + + if (!has_new_bits(virgin_crash)) return keeping; + + } + + if (!unique_crashes) write_crash_readme(); + +#ifndef SIMPLE_FILES + + fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", out_dir, + unique_crashes, kill_signal, describe_op(0)); + +#else + + fn = alloc_printf("%s/crashes/id_%06llu_%02u", out_dir, unique_crashes, + kill_signal); + +#endif /* ^!SIMPLE_FILES */ + + unique_crashes++; + + last_crash_time = get_cur_time(); + last_crash_execs = total_execs; + + break; + + case FAULT_ERROR: FATAL("Unable to execute target application"); + + default: return keeping; + + } + + /* If we're here, we apparently want to save the crash or hang + test case, too. */ + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + ck_write(fd, mem, len, fn); + close(fd); + + ck_free(fn); + + return keeping; + +} + + +/* When resuming, try to find the queue position to start from. This makes sense + only when resuming, and when we can find the original fuzzer_stats. */ + +static u32 find_start_position(void) { + + static u8 tmp[4096]; /* Ought to be enough for anybody. */ + + u8 *fn, *off; + s32 fd, i; + u32 ret; + + if (!resuming_fuzz) return 0; + + if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); + else fn = alloc_printf("%s/../fuzzer_stats", in_dir); + + fd = open(fn, O_RDONLY); + ck_free(fn); + + if (fd < 0) return 0; + + i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ + close(fd); + + off = strstr((const char*)tmp, "cur_path : "); + if (!off) return 0; + + ret = atoi(off + 20); + if (ret >= queued_paths) ret = 0; + return ret; + +} + + +/* The same, but for timeouts. The idea is that when resuming sessions without + -t given, we don't want to keep auto-scaling the timeout over and over + again to prevent it from growing due to random flukes. */ + +static void find_timeout(void) { + + static u8 tmp[4096]; /* Ought to be enough for anybody. */ + + u8 *fn, *off; + s32 fd, i; + u32 ret; + + if (!resuming_fuzz) return; + + if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); + else fn = alloc_printf("%s/../fuzzer_stats", in_dir); + + fd = open(fn, O_RDONLY); + ck_free(fn); + + if (fd < 0) return; + + i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ + close(fd); + + off = strstr((const char*)tmp, "exec_timeout : "); + if (!off) return; + + ret = atoi(off + 20); + if (ret <= 4) return; + + exec_tmout = ret; + timeout_given = 3; + +} + + +/* Update stats file for unattended monitoring. */ + +static void write_stats_file(double bitmap_cvg, double stability, double eps) { + + static double last_bcvg, last_stab, last_eps; + static struct rusage usage; + + u8* fn = alloc_printf("%s/fuzzer_stats", out_dir); + s32 fd; + FILE* f; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + + f = fdopen(fd, "w"); + + if (!f) PFATAL("fdopen() failed"); + + /* Keep last values in case we're called from another context + where exec/sec stats and such are not readily available. */ + + if (!bitmap_cvg && !stability && !eps) { + bitmap_cvg = last_bcvg; + stability = last_stab; + eps = last_eps; + } else { + last_bcvg = bitmap_cvg; + last_stab = stability; + last_eps = eps; + } + + fprintf(f, "start_time : %llu\n" + "last_update : %llu\n" + "fuzzer_pid : %u\n" + "cycles_done : %llu\n" + "execs_done : %llu\n" + "total_vaild : %llu\n" + "execs_per_sec : %0.02f\n" + "paths_total : %u\n" + "paths_favored : %u\n" + "paths_found : %u\n" + "paths_imported : %u\n" + "max_depth : %u\n" + "cur_path : %u\n" /* Must match find_start_position() */ + "pending_favs : %u\n" + "pending_total : %u\n" + "variable_paths : %u\n" + "stability : %0.02f%%\n" + "bitmap_cvg : %0.02f%%\n" + "unique_crashes : %llu\n" + "unique_hangs : %llu\n" + "last_path : %llu\n" + "last_crash : %llu\n" + "last_hang : %llu\n" + "execs_since_crash : %llu\n" + "exec_timeout : %u\n" /* Must match find_timeout() */ + "afl_banner : %s\n" + "afl_version : " VERSION "\n" + "target_mode : %s%s%s%s%s%s%s\n" + "command_line : %s\n" + "slowest_exec_ms : %llu\n", + start_time / 1000, get_cur_time() / 1000, getpid(), + queue_cycle ? (queue_cycle - 1) : 0, total_execs, total_vaild, eps, + queued_paths, queued_favored, queued_discovered, queued_imported, + max_depth, current_entry, pending_favored, pending_not_fuzzed, + queued_variable, stability, bitmap_cvg, unique_crashes, + unique_hangs, last_path_time / 1000, last_crash_time / 1000, + last_hang_time / 1000, total_execs - last_crash_execs, + exec_tmout, use_banner, + qemu_mode ? "qemu " : "", dumb_mode ? " dumb " : "", + no_forkserver ? "no_forksrv " : "", crash_mode ? "crash " : "", + persistent_mode ? "persistent " : "", deferred_mode ? "deferred " : "", + (qemu_mode || dumb_mode || no_forkserver || crash_mode || + persistent_mode || deferred_mode) ? "" : "default", + orig_cmdline, slowest_exec_ms); + + fprintf(f, "mutate total : %llu\n", g_mutator.totalMutate_); + fprintf(f, "mutate failed : %llu\n", g_mutator.failedMutate_); + /* ignore errors */ + /* Get rss value from the children + We must have killed the forkserver process and called waitpid + before calling getrusage */ + if (getrusage(RUSAGE_CHILDREN, &usage)) { + WARNF("getrusage failed"); + } else if (usage.ru_maxrss == 0) { + fprintf(f, "peak_rss_mb : not available while afl is running\n"); + } else { +#ifdef __APPLE__ + fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss >> 20); +#else + fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss >> 10); +#endif /* ^__APPLE__ */ + } + + fclose(f); + +} + + +/* Update the plot file if there is a reason to. */ + +static void maybe_update_plot_file(double bitmap_cvg, double eps) { + + static u32 prev_qp, prev_pf, prev_pnf, prev_ce, prev_md; + static u64 prev_qc, prev_uc, prev_uh; + + if (prev_qp == queued_paths && prev_pf == pending_favored && + prev_pnf == pending_not_fuzzed && prev_ce == current_entry && + prev_qc == queue_cycle && prev_uc == unique_crashes && + prev_uh == unique_hangs && prev_md == max_depth) return; + + prev_qp = queued_paths; + prev_pf = pending_favored; + prev_pnf = pending_not_fuzzed; + prev_ce = current_entry; + prev_qc = queue_cycle; + prev_uc = unique_crashes; + prev_uh = unique_hangs; + prev_md = max_depth; + + /* Fields in the file: + + unix_time, cycles_done, cur_path, paths_total, paths_not_fuzzed, + favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, + execs_per_sec */ + + fprintf(plot_file, + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, %llu, %llu\n", + get_cur_time() / 1000, queue_cycle - 1, current_entry, queued_paths, + pending_not_fuzzed, pending_favored, bitmap_cvg, unique_crashes, + unique_hangs, max_depth, eps, total_execs, total_vaild, seed_count); + + fflush(plot_file); + +} + + + +/* A helper function for maybe_delete_out_dir(), deleting all prefixed + files in a directory. */ + +static u8 delete_files(u8* path, u8* prefix) { + + DIR* d; + struct dirent* d_ent; + + d = opendir(path); + + if (!d) return 0; + + while ((d_ent = readdir(d))) { + + if (d_ent->d_name[0] != '.' && (!prefix || + !strncmp(d_ent->d_name, prefix, strlen(prefix)))) { + + u8* fname = alloc_printf("%s/%s", path, d_ent->d_name); + if (unlink(fname)) PFATAL("Unable to delete '%s'", fname); + ck_free(fname); + + } + + } + + closedir(d); + + return !!rmdir(path); + +} + + +/* Get the number of runnable processes, with some simple smoothing. */ + +static double get_runnable_processes(void) { + + static double res; + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) + + /* I don't see any portable sysctl or so that would quickly give us the + number of runnable processes; the 1-minute load average can be a + semi-decent approximation, though. */ + + if (getloadavg(&res, 1) != 1) return 0; + +#else + + /* On Linux, /proc/stat is probably the best way; load averages are + computed in funny ways and sometimes don't reflect extremely short-lived + processes well. */ + + FILE* f = fopen("/proc/stat", "r"); + u8 tmp[1024]; + u32 val = 0; + + if (!f) return 0; + + while (fgets(tmp, sizeof(tmp), f)) { + + if (!strncmp(tmp, "procs_running ", 14) || + !strncmp(tmp, "procs_blocked ", 14)) val += atoi(tmp + 14); + + } + + fclose(f); + + if (!res) { + + res = val; + + } else { + + res = res * (1.0 - 1.0 / AVG_SMOOTHING) + + ((double)val) * (1.0 / AVG_SMOOTHING); + + } + +#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ + + return res; + +} + + +/* Delete the temporary directory used for in-place session resume. */ + +static void nuke_resume_dir(void) { + + u8* fn; + + fn = alloc_printf("%s/_resume/.state/deterministic_done", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state/auto_extras", out_dir); + if (delete_files(fn, "auto_")) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state/redundant_edges", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state/variable_behavior", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state", out_dir); + if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + return; + +dir_cleanup_failed: + + FATAL("_resume directory cleanup failed"); + +} + + +/* Delete fuzzer output directory if we recognize it as ours, if the fuzzer + is not currently running, and if the last run time isn't too great. */ + +static void maybe_delete_out_dir(void) { + + FILE* f; + u8 *fn = alloc_printf("%s/fuzzer_stats", out_dir); + + /* See if the output directory is locked. If yes, bail out. If not, + create a lock that will persist for the lifetime of the process + (this requires leaving the descriptor open).*/ + + out_dir_fd = open(out_dir, O_RDONLY); + if (out_dir_fd < 0) PFATAL("Unable to open '%s'", out_dir); + +#ifndef __sun + + if (flock(out_dir_fd, LOCK_EX | LOCK_NB) && errno == EWOULDBLOCK) { + + SAYF("\n" cLRD "[-] " cRST + "Looks like the job output directory is being actively used by another\n" + " instance of afl-fuzz. You will need to choose a different %s\n" + " or stop the other process first.\n", + sync_id ? "fuzzer ID" : "output location"); + + FATAL("Directory '%s' is in use", out_dir); + + } + +#endif /* !__sun */ + + f = fopen(fn, "r"); + + if (f) { + + u64 start_time, last_update; + + if (fscanf(f, "start_time : %llu\n" + "last_update : %llu\n", &start_time, &last_update) != 2) + FATAL("Malformed data in '%s'", fn); + + fclose(f); + + /* Let's see how much work is at stake. */ + + if (!in_place_resume && last_update - start_time > OUTPUT_GRACE * 60) { + + SAYF("\n" cLRD "[-] " cRST + "The job output directory already exists and contains the results of more\n" + " than %u minutes worth of fuzzing. To avoid data loss, afl-fuzz will *NOT*\n" + " automatically delete this data for you.\n\n" + + " If you wish to start a new session, remove or rename the directory manually,\n" + " or specify a different output location for this job. To resume the old\n" + " session, put '-' as the input directory in the command line ('-i -') and\n" + " try again.\n", OUTPUT_GRACE); + + FATAL("At-risk data found in '%s'", out_dir); + + } + + } + + ck_free(fn); + + /* The idea for in-place resume is pretty simple: we temporarily move the old + queue/ to a new location that gets deleted once import to the new queue/ + is finished. If _resume/ already exists, the current queue/ may be + incomplete due to an earlier abort, so we want to use the old _resume/ + dir instead, and we let rename() fail silently. */ + + if (in_place_resume) { + + u8* orig_q = alloc_printf("%s/queue", out_dir); + + in_dir = alloc_printf("%s/_resume", out_dir); + + rename(orig_q, in_dir); /* Ignore errors */ + + OKF("Output directory exists, will attempt session resume."); + + ck_free(orig_q); + + } else { + + OKF("Output directory exists but deemed OK to reuse."); + + } + + ACTF("Deleting old session data..."); + + /* Okay, let's get the ball rolling! First, we need to get rid of the entries + in /.synced/.../id:*, if any are present. */ + + if (!in_place_resume) { + + fn = alloc_printf("%s/.synced", out_dir); + if (delete_files(fn, NULL)) goto dir_cleanup_failed; + ck_free(fn); + + } + + /* Next, we need to clean up /queue/.state/ subdirectories: */ + + fn = alloc_printf("%s/queue/.state/deterministic_done", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue/.state/auto_extras", out_dir); + if (delete_files(fn, "auto_")) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue/.state/redundant_edges", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue/.state/variable_behavior", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + /* Then, get rid of the .state subdirectory itself (should be empty by now) + and everything matching /queue/id:*. */ + + fn = alloc_printf("%s/queue/.state", out_dir); + if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + /* All right, let's do /crashes/id:* and /hangs/id:*. */ + + if (!in_place_resume) { + + fn = alloc_printf("%s/crashes/README.txt", out_dir); + unlink(fn); /* Ignore errors */ + ck_free(fn); + + } + + fn = alloc_printf("%s/crashes", out_dir); + + /* Make backup of the crashes directory if it's not empty and if we're + doing in-place resume. */ + + if (in_place_resume && rmdir(fn)) { + + time_t cur_t = time(0); + struct tm* t = localtime(&cur_t); + +#ifndef SIMPLE_FILES + + u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#else + + u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#endif /* ^!SIMPLE_FILES */ + + rename(fn, nfn); /* Ignore errors. */ + ck_free(nfn); + + } + + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/hangs", out_dir); + + /* Backup hangs, too. */ + + if (in_place_resume && rmdir(fn)) { + + time_t cur_t = time(0); + struct tm* t = localtime(&cur_t); + +#ifndef SIMPLE_FILES + + u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#else + + u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#endif /* ^!SIMPLE_FILES */ + + rename(fn, nfn); /* Ignore errors. */ + ck_free(nfn); + + } + + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + /* And now, for some finishing touches. */ + + fn = alloc_printf("%s/.cur_input", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/fuzz_bitmap", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + if (!in_place_resume) { + fn = alloc_printf("%s/fuzzer_stats", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + } + + fn = alloc_printf("%s/plot_data", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + OKF("Output dir cleanup successful."); + + /* Wow... is that all? If yes, celebrate! */ + + return; + +dir_cleanup_failed: + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the fuzzer tried to reuse your output directory, but bumped into\n" + " some files that shouldn't be there or that couldn't be removed - so it\n" + " decided to abort! This happened while processing this path:\n\n" + + " %s\n\n" + " Please examine and manually delete the files, or specify a different\n" + " output location for the tool.\n", fn); + + FATAL("Output directory cleanup failed"); + +} + + +static void check_term_size(void); + + +/* A spiffy retro stats screen! This is called every stats_update_freq + execve() calls, plus in several other circumstances. */ + +static void show_stats(void) { + + static u64 last_stats_ms, last_plot_ms, last_ms, last_execs; + static double avg_exec; + double t_byte_ratio, stab_ratio; + + u64 cur_ms; + u32 t_bytes, t_bits; + + u32 banner_len, banner_pad; + u8 tmp[256]; + + cur_ms = get_cur_time(); + + /* If not enough time has passed since last UI update, bail out. */ + + if (cur_ms - last_ms < 1000 / UI_TARGET_HZ) return; + + /* Check if we're past the 10 minute mark. */ + + if (cur_ms - start_time > 10 * 60 * 1000) run_over10m = 1; + + /* Calculate smoothed exec speed stats. */ + + if (!last_execs) { + + avg_exec = ((double)total_execs) * 1000 / (cur_ms - start_time); + + } else { + + double cur_avg = ((double)(total_execs - last_execs)) * 1000 / + (cur_ms - last_ms); + + /* If there is a dramatic (5x+) jump in speed, reset the indicator + more quickly. */ + + if (cur_avg * 5 < avg_exec || cur_avg / 5 > avg_exec) + avg_exec = cur_avg; + + avg_exec = avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + + cur_avg * (1.0 / AVG_SMOOTHING); + + } + + last_ms = cur_ms; + last_execs = total_execs; + + /* Tell the callers when to contact us (as measured in execs). */ + + stats_update_freq = avg_exec / (UI_TARGET_HZ * 10); + if (!stats_update_freq) stats_update_freq = 1; + + /* Do some bitmap stats. */ + + t_bytes = count_non_255_bytes(virgin_bits); + t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE; + + if (t_bytes) + stab_ratio = 100 - ((double)var_byte_count) * 100 / t_bytes; + else + stab_ratio = 100; + + /* Roughly every minute, update fuzzer stats and save auto tokens. */ + + if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) { + + last_stats_ms = cur_ms; + write_stats_file(t_byte_ratio, stab_ratio, avg_exec); + save_auto(); + write_bitmap(); + + } + + /* Every now and then, write plot data. */ + + if (cur_ms - last_plot_ms > PLOT_UPDATE_SEC * 1000) { + + last_plot_ms = cur_ms; + maybe_update_plot_file(t_byte_ratio, avg_exec); + + } + + /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ + + if (!dumb_mode && cycles_wo_finds > 100 && !pending_not_fuzzed && + getenv("AFL_EXIT_WHEN_DONE")) stop_soon = 2; + + if (total_crashes && getenv("AFL_BENCH_UNTIL_CRASH")) stop_soon = 2; + + /* If we're not on TTY, bail out. */ + + if (not_on_tty) return; + + /* Compute some mildly useful bitmap stats. */ + + t_bits = (MAP_SIZE << 3) - count_bits(virgin_bits); + + /* Now, for the visuals... */ + + if (clear_screen) { + + SAYF(TERM_CLEAR CURSOR_HIDE); + clear_screen = 0; + + check_term_size(); + + } + + SAYF(TERM_HOME); + + if (term_too_small) { + + SAYF(cBRI "Your terminal is too small to display the UI.\n" + "Please resize terminal window to at least 80x25.\n" cRST); + + return; + + } + + /* Let's start by drawing a centered banner. */ + + banner_len = (crash_mode ? 24 : 22) + strlen(VERSION) + strlen(use_banner); + banner_pad = (80 - banner_len) / 2; + memset(tmp, ' ', banner_pad); + + sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN + " (%s)", crash_mode ? cPIN "peruvian were-rabbit" : + cYEL "american fuzzy lop", use_banner); + + SAYF("\n%s\n\n", tmp); + + /* "Handy" shortcuts for drawing boxes... */ + +#define bSTG bSTART cGRA +#define bH2 bH bH +#define bH5 bH2 bH2 bH +#define bH10 bH5 bH5 +#define bH20 bH10 bH10 +#define bH30 bH20 bH10 +#define SP5 " " +#define SP10 SP5 SP5 +#define SP20 SP10 SP10 + + /* Lord, forgive me this. */ + + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH2 bHB + bH bSTOP cCYA " overall results " bSTG bH5 bRT "\n"); + + if (dumb_mode) { + + strcpy(tmp, cRST); + + } else { + + u64 min_wo_finds = (cur_ms - last_path_time) / 1000 / 60; + + /* First queue cycle: don't stop now! */ + if (queue_cycle == 1 || min_wo_finds < 15) strcpy(tmp, cMGN); else + + /* Subsequent cycles, but we're still making finds. */ + if (cycles_wo_finds < 25 || min_wo_finds < 30) strcpy(tmp, cYEL); else + + /* No finds for a long time and no test cases to try. */ + if (cycles_wo_finds > 100 && !pending_not_fuzzed && min_wo_finds > 120) + strcpy(tmp, cLGN); + + /* Default: cautiously OK to stop? */ + else strcpy(tmp, cLBL); + + } + + SAYF(bV bSTOP " run time : " cRST "%-34s " bSTG bV bSTOP + " cycles done : %s%-5s " bSTG bV "\n", + DTD(cur_ms, start_time), tmp, DI(queue_cycle - 1)); + + /* We want to warn people about not seeing new paths after a full cycle, + except when resuming fuzzing or running in non-instrumented mode. */ + + if (!dumb_mode && (last_path_time || resuming_fuzz || queue_cycle == 1 || + in_bitmap || crash_mode)) { + + SAYF(bV bSTOP " last new path : " cRST "%-34s ", + DTD(cur_ms, last_path_time)); + + } else { + + if (dumb_mode) + + SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST + " (non-instrumented mode) "); + + else + + SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD + "(odd, check syntax!) "); + + } + + SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n", + DI(queued_paths)); + + /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH + limit with a '+' appended to the count. */ + + sprintf(tmp, "%s%s", DI(unique_crashes), + (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + SAYF(bV bSTOP " last uniq crash : " cRST "%-34s " bSTG bV bSTOP + " uniq crashes : %s%-6s " bSTG bV "\n", + DTD(cur_ms, last_crash_time), unique_crashes ? cLRD : cRST, + tmp); + + sprintf(tmp, "%s%s", DI(unique_hangs), + (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + + SAYF(bV bSTOP " last uniq hang : " cRST "%-34s " bSTG bV bSTOP + " uniq hangs : " cRST "%-6s " bSTG bV "\n", + DTD(cur_ms, last_hang_time), tmp); + + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH20 bHB bH bSTOP cCYA + " map coverage " bSTG bH bHT bH20 bH2 bH bVL "\n"); + + /* This gets funny because we want to print several variable-length variables + together, but then cram them into a fixed-width field - so we need to + put them in a temporary buffer first. */ + + sprintf(tmp, "%s%s (%0.02f%%)", DI(current_entry), + queue_cur->favored ? "" : "*", + ((double)current_entry * 100) / queued_paths); + + SAYF(bV bSTOP " now processing : " cRST "%-17s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * + 100 / MAP_SIZE, t_byte_ratio); + + SAYF(" map density : %s%-21s " bSTG bV "\n", t_byte_ratio > 70 ? cLRD : + ((t_bytes < 200 && !dumb_mode) ? cPIN : cRST), tmp); + + sprintf(tmp, "%s (%0.02f%%)", DI(cur_skipped_paths), + ((double)cur_skipped_paths * 100) / queued_paths); + + SAYF(bV bSTOP " paths timed out : " cRST "%-17s " bSTG bV, tmp); + + sprintf(tmp, "%0.02f bits/tuple", + t_bytes ? (((double)t_bits) / t_bytes) : 0); + + SAYF(bSTOP " count coverage : " cRST "%-21s " bSTG bV "\n", tmp); + + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH20 bX bH bSTOP cCYA + " findings in depth " bSTG bH20 bVL "\n"); + + /* Yeah... it's still going on... halp? */ + + sprintf(tmp, "%s (%0.02f%%)", DI(total_vaild), + total_execs ? ((double)total_vaild) * 100 / total_execs : (double)0); + + SAYF(bV bSTOP " total vaild : " cRST "%-21s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%s (%0.02f%%)", DI(queued_favored), + ((double)queued_favored) * 100 / queued_paths); + + SAYF(" favored paths : " cRST "%-22s " bSTG bV "\n", tmp); + + if (!stage_max) { + + sprintf(tmp, "%s/-", DI(stage_cur)); + + } else { + + sprintf(tmp, "%s/%s (%0.02f%%)", DI(stage_cur), DI(stage_max), + ((double)stage_cur) * 100 / stage_max); + + } + + SAYF(bV bSTOP " stage execs : " cRST "%-21s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%s (%0.02f%%)", DI(queued_with_cov), + ((double)queued_with_cov) * 100 / queued_paths); + + SAYF(" new edges on : " cRST "%-22s " bSTG bV "\n", tmp); + + sprintf(tmp, "%s (%s%s unique)", DI(total_crashes), DI(unique_crashes), + (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + if (crash_mode) { + + SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP + " new crashes : %s%-22s " bSTG bV "\n", DI(total_execs), + unique_crashes ? cLRD : cRST, tmp); + + } else { + + SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP + " total crashes : %s%-22s " bSTG bV "\n", DI(total_execs), + unique_crashes ? cLRD : cRST, tmp); + + } + + /* Show a warning about slow execution. */ + + if (avg_exec < 100) { + + sprintf(tmp, "%s/sec (%s)", DF(avg_exec), avg_exec < 20 ? + "zzzz..." : "slow!"); + + SAYF(bV bSTOP " exec speed : " cLRD "%-21s ", tmp); + + } else { + + sprintf(tmp, "%s/sec", DF(avg_exec)); + SAYF(bV bSTOP " exec speed : " cRST "%-21s ", tmp); + + } + + sprintf(tmp, "%s (%s%s unique)", DI(total_tmouts), DI(unique_tmouts), + (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + + SAYF (bSTG bV bSTOP " total tmouts : " cRST "%-22s " bSTG bV "\n", tmp); + + /* Aaaalmost there... hold on! */ + + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH bHT bH10 + bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bH bVL "\n"); + + if (skip_deterministic) { + + strcpy(tmp, "n/a, n/a, n/a"); + + } else { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_FLIP1]), DI(stage_cycles[STAGE_FLIP1]), + DI(stage_finds[STAGE_FLIP2]), DI(stage_cycles[STAGE_FLIP2]), + DI(stage_finds[STAGE_FLIP4]), DI(stage_cycles[STAGE_FLIP4])); + + } + + SAYF(bV bSTOP " bit flips : " cRST "%-37s " bSTG bV bSTOP " levels : " + cRST "%-10s " bSTG bV "\n", tmp, DI(max_depth)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_FLIP8]), DI(stage_cycles[STAGE_FLIP8]), + DI(stage_finds[STAGE_FLIP16]), DI(stage_cycles[STAGE_FLIP16]), + DI(stage_finds[STAGE_FLIP32]), DI(stage_cycles[STAGE_FLIP32])); + + SAYF(bV bSTOP " byte flips : " cRST "%-37s " bSTG bV bSTOP " pending : " + cRST "%-10s " bSTG bV "\n", tmp, DI(pending_not_fuzzed)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_ARITH8]), DI(stage_cycles[STAGE_ARITH8]), + DI(stage_finds[STAGE_ARITH16]), DI(stage_cycles[STAGE_ARITH16]), + DI(stage_finds[STAGE_ARITH32]), DI(stage_cycles[STAGE_ARITH32])); + + SAYF(bV bSTOP " arithmetics : " cRST "%-37s " bSTG bV bSTOP " pend fav : " + cRST "%-10s " bSTG bV "\n", tmp, DI(pending_favored)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_INTEREST8]), DI(stage_cycles[STAGE_INTEREST8]), + DI(stage_finds[STAGE_INTEREST16]), DI(stage_cycles[STAGE_INTEREST16]), + DI(stage_finds[STAGE_INTEREST32]), DI(stage_cycles[STAGE_INTEREST32])); + + SAYF(bV bSTOP " known ints : " cRST "%-37s " bSTG bV bSTOP " own finds : " + cRST "%-10s " bSTG bV "\n", tmp, DI(queued_discovered)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_EXTRAS_UO]), DI(stage_cycles[STAGE_EXTRAS_UO]), + DI(stage_finds[STAGE_EXTRAS_UI]), DI(stage_cycles[STAGE_EXTRAS_UI]), + DI(stage_finds[STAGE_EXTRAS_AO]), DI(stage_cycles[STAGE_EXTRAS_AO])); + + SAYF(bV bSTOP " dictionary : " cRST "%-37s " bSTG bV bSTOP + " imported : " cRST "%-10s " bSTG bV "\n", tmp, + sync_id ? DI(queued_imported) : (u8*)"n/a"); + + sprintf(tmp, "%s/%s, %s/%s", + DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), + DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE])); + + SAYF(bV bSTOP " havoc : " cRST "%-37s " bSTG bV bSTOP, tmp); + + if (t_bytes) sprintf(tmp, "%0.02f%%", stab_ratio); + else strcpy(tmp, "n/a"); + + SAYF(" stability : %s%-10s " bSTG bV "\n", (stab_ratio < 85 && var_byte_count > 40) + ? cLRD : ((queued_variable && (!persistent_mode || var_byte_count > 20)) + ? cMGN : cRST), tmp); + + if (!bytes_trim_out) { + + sprintf(tmp, "n/a, "); + + } else { + + sprintf(tmp, "%0.02f%%/%s, ", + ((double)(bytes_trim_in - bytes_trim_out)) * 100 / bytes_trim_in, + DI(trim_execs)); + + } + + if (!blocks_eff_total) { + + u8 tmp2[128]; + + sprintf(tmp2, "n/a"); + strcat(tmp, tmp2); + + } else { + + u8 tmp2[128]; + + sprintf(tmp2, "%0.02f%%", + ((double)(blocks_eff_total - blocks_eff_select)) * 100 / + blocks_eff_total); + + strcat(tmp, tmp2); + + } + + SAYF(bV bSTOP " trim : " cRST "%-37s " bSTG bVR bH20 bH2 bH2 bRB "\n" + bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1, tmp); + + /* Provide some CPU utilization stats. */ + + if (cpu_core_count) { + + double cur_runnable = get_runnable_processes(); + u32 cur_utilization = cur_runnable * 100 / cpu_core_count; + + u8* cpu_color = cCYA; + + /* If we could still run one or more processes, use green. */ + + if (cpu_core_count > 1 && cur_runnable + 1 <= cpu_core_count) + cpu_color = cLGN; + + /* If we're clearly oversubscribed, use red. */ + + if (!no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD; + +#ifdef HAVE_AFFINITY + + if (cpu_aff >= 0) { + + SAYF(SP10 cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, + MIN(cpu_aff, 999), cpu_color, + MIN(cur_utilization, 999)); + + } else { + + SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, + cpu_color, MIN(cur_utilization, 999)); + + } + +#else + + SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, + cpu_color, MIN(cur_utilization, 999)); + +#endif /* ^HAVE_AFFINITY */ + + } else SAYF("\r"); + + /* Hallelujah! */ + + fflush(0); + + if (get_cur_time() - last_save_time > 60 * 60 * 1000) { + u8* fn = alloc_printf("%s/coverage_statistics", out_dir); + + FILE* fd = fopen(fn, "a+"); + + if (!fd) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + + fprintf(fd, "%d\t%d\t%d (%0.02f%%)\t%d(%0.02f%%)\n", (unsigned int)((get_cur_time() - start_time) / (60 * 60 * 1000)), queued_paths, total_vaild, total_execs ? ((double)total_vaild) * 100 / total_execs : (double)0, t_bytes, t_byte_ratio); + + fclose(fd); + + last_save_time = get_cur_time(); + } + +} + + +/* Display quick statistics at the end of processing the input directory, + plus a bunch of warnings. Some calibration stuff also ended up here, + along with several hardcoded constants. Maybe clean up eventually. */ + +static void show_init_stats(void) { + + struct queue_entry* q = queue; + u32 min_bits = 0, max_bits = 0; + u64 min_us = 0, max_us = 0; + u64 avg_us = 0; + u32 max_len = 0; + + if (total_cal_cycles) avg_us = total_cal_us / total_cal_cycles; + + while (q) { + + if (!min_us || q->exec_us < min_us) min_us = q->exec_us; + if (q->exec_us > max_us) max_us = q->exec_us; + + if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size; + if (q->bitmap_size > max_bits) max_bits = q->bitmap_size; + + if (q->len > max_len) max_len = q->len; + + q = q->next; + + } + + SAYF("\n"); + + if (avg_us > (qemu_mode ? 50000 : 10000)) + WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.txt.", + doc_path); + + /* Let's keep things moving with slow binaries. */ + + if (avg_us > 50000) havoc_div = 10; /* 0-19 execs/sec */ + else if (avg_us > 20000) havoc_div = 5; /* 20-49 execs/sec */ + else if (avg_us > 10000) havoc_div = 2; /* 50-100 execs/sec */ + + if (!resuming_fuzz) { + + if (max_len > 50 * 1024) + WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.txt!", + DMS(max_len), doc_path); + else if (max_len > 10 * 1024) + WARNF("Some test cases are big (%s) - see %s/perf_tips.txt.", + DMS(max_len), doc_path); + + if (useless_at_start && !in_bitmap) + WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); + + if (queued_paths > 100) + WARNF(cLRD "You probably have far too many input files! Consider trimming down."); + else if (queued_paths > 20) + WARNF("You have lots of input files; try starting small."); + + } + + OKF("Here are some useful stats:\n\n" + + cGRA " Test case count : " cRST "%u favored, %u variable, %u total\n" + cGRA " Bitmap range : " cRST "%u to %u bits (average: %0.02f bits)\n" + cGRA " Exec timing : " cRST "%s to %s us (average: %s us)\n", + queued_favored, queued_variable, queued_paths, min_bits, max_bits, + ((double)total_bitmap_size) / (total_bitmap_entries ? total_bitmap_entries : 1), + DI(min_us), DI(max_us), DI(avg_us)); + + if (!timeout_given) { + + /* Figure out the appropriate timeout. The basic idea is: 5x average or + 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. + + If the program is slow, the multiplier is lowered to 2x or 3x, because + random scheduler jitter is less likely to have any impact, and because + our patience is wearing thin =) */ + + if (avg_us > 50000) exec_tmout = avg_us * 2 / 1000; + else if (avg_us > 10000) exec_tmout = avg_us * 3 / 1000; + else exec_tmout = avg_us * 5 / 1000; + + exec_tmout = MAX(exec_tmout, max_us / 1000); + exec_tmout = (exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; + + if (exec_tmout > EXEC_TIMEOUT) exec_tmout = EXEC_TIMEOUT; + + ACTF("No -t option specified, so I'll use exec timeout of %u ms.", + exec_tmout); + + timeout_given = 1; + + } else if (timeout_given == 3) { + + ACTF("Applying timeout settings from resumed session (%u ms).", exec_tmout); + + } + + /* In dumb mode, re-running every timing out test case with a generous time + limit is very expensive, so let's select a more conservative default. */ + + if (dumb_mode && !getenv("AFL_HANG_TMOUT")) + hang_tmout = MIN(EXEC_TIMEOUT, exec_tmout * 2 + 100); + + OKF("All set and ready to roll!"); + +} + + +/* Find first power of two greater or equal to val (assuming val under + 2^31). */ + +static u32 next_p2(u32 val) { + + u32 ret = 1; + while (val > ret) ret <<= 1; + return ret; + +} + + +/* Trim all new test cases to save cycles when doing deterministic checks. The + trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of + file size, to keep the stage short and sweet. */ + +static u8 trim_case(char** argv, struct queue_entry* q, u8* in_buf) { + + static u8 tmp[64]; + static u8 clean_trace[MAP_SIZE]; + + u8 needs_write = 0, fault = 0; + u32 trim_exec = 0; + u32 remove_len; + u32 len_p2; + + /* Although the trimmer will be less useful when variable behavior is + detected, it will still work to some extent, so we don't check for + this. */ + + if (q->len < 5) return 0; + + stage_name = tmp; + bytes_trim_in += q->len; + + /* Select initial chunk len, starting with large steps. */ + + len_p2 = next_p2(q->len); + + remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES); + + /* Continue until the number of steps gets too high or the stepover + gets too small. */ + + while (remove_len >= MAX(len_p2 / TRIM_END_STEPS, TRIM_MIN_BYTES)) { + + u32 remove_pos = remove_len; + + sprintf(tmp, "trim %s/%s", DI(remove_len), DI(remove_len)); + + stage_cur = 0; + stage_max = q->len / remove_len; + + while (remove_pos < q->len) { + + u32 trim_avail = MIN(remove_len, q->len - remove_pos); + u32 cksum; + + write_with_gap(in_buf, q->len, remove_pos, trim_avail); + + fault = run_target(argv, exec_tmout); + trim_execs++; + + if (stop_soon || fault == FAULT_ERROR) goto abort_trimming; + + /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ + + cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + + /* If the deletion had no impact on the trace, make it permanent. This + isn't perfect for variable-path inputs, but we're just making a + best-effort pass, so it's not a big deal if we end up with false + negatives every now and then. */ + + if (cksum == q->exec_cksum) { + + u32 move_tail = q->len - remove_pos - trim_avail; + + q->len -= trim_avail; + len_p2 = next_p2(q->len); + + memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, + move_tail); + + /* Let's save a clean trace, which will be needed by + update_bitmap_score once we're done with the trimming stuff. */ + + if (!needs_write) { + + needs_write = 1; + memcpy(clean_trace, trace_bits, MAP_SIZE); + + } + + } else remove_pos += remove_len; + + /* Since this can be slow, update the screen every now and then. */ + + if (!(trim_exec++ % stats_update_freq)) show_stats(); + stage_cur++; + + } + + remove_len >>= 1; + + } + + /* If we have made changes to in_buf, we also need to update the on-disk + version of the test case. */ + + if (needs_write) { + + s32 fd; + + unlink(q->fname); /* ignore errors */ + + fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", q->fname); + + ck_write(fd, in_buf, q->len, q->fname); + close(fd); + + memcpy(trace_bits, clean_trace, MAP_SIZE); + update_bitmap_score(q); + + } + +abort_trimming: + + bytes_trim_out += q->len; + return fault; + +} + +int num = 0; +/* Write a modified test case, run program, process results. Handle + error conditions, returning 1 if it's time to bail out. This is + a helper function for fuzz_one(). */ + +EXP_ST u8 common_fuzz_stuff(char** argv, const u8* out_buf, u32 len) { + + u8 fault; + u8 tmp_vaild_flag; + + //cout << num ++ << ":" << out_buf << endl; + if (post_handler) { + + out_buf = post_handler(out_buf, &len); + if (!out_buf || !len) return 0; + + } + write_to_testcase(out_buf, len); + + fault = run_target(argv, exec_tmout); + + tmp_vaild_flag = vaild_flag; + + if (stop_soon) return 1; + + if (fault == FAULT_TMOUT) { + + if (subseq_tmouts++ > TMOUT_LIMIT) { + cur_skipped_paths++; + return 1; + } + + } else subseq_tmouts = 0; + + /* Users can hit us with SIGUSR1 to request the current input + to be abandoned. */ + + if (skip_requested) { + + skip_requested = 0; + cur_skipped_paths++; + return 1; + + } + + /* This handles FAULT_ERROR for us: */ + //cout << num ++ << ":" << out_buf << endl; + int should_keep = save_if_interesting(argv, out_buf, len, fault); + queued_discovered += (should_keep == 1 || should_keep == 2); + + g_mutator.update_status(g_current_input, should_keep, tmp_vaild_flag); + + //cout << "OK" << endl; + if (!(stage_cur % stats_update_freq) || stage_cur + 1 == stage_max) + show_stats(); + + return 0; + +} + + +/* Helper to choose random block len for block operations in fuzz_one(). + Doesn't return zero, provided that max_len is > 0. */ + +static u32 choose_block_len(u32 limit) { + + u32 min_value, max_value; + u32 rlim = MIN(queue_cycle, 3); + + if (!run_over10m) rlim = 1; + + switch (UR(rlim)) { + + case 0: min_value = 1; + max_value = HAVOC_BLK_SMALL; + break; + + case 1: min_value = HAVOC_BLK_SMALL; + max_value = HAVOC_BLK_MEDIUM; + break; + + default: + + if (UR(10)) { + + min_value = HAVOC_BLK_MEDIUM; + max_value = HAVOC_BLK_LARGE; + + } else { + + min_value = HAVOC_BLK_LARGE; + max_value = HAVOC_BLK_XL; + + } + + } + + if (min_value >= limit) min_value = 1; + + return min_value + UR(MIN(max_value, limit) - min_value + 1); + +} + + +/* Calculate case desirability score to adjust the length of havoc fuzzing. + A helper function for fuzz_one(). Maybe some of these constants should + go into config.h. */ + +static u32 calculate_score(struct queue_entry* q) { + + u32 avg_exec_us = total_cal_us / (total_cal_cycles+1); + u32 avg_bitmap_size = total_bitmap_size / (total_bitmap_entries+1); + u32 perf_score = 100; + + /* Adjust score based on execution speed of this path, compared to the + global average. Multiplier ranges from 0.1x to 3x. Fast inputs are + less expensive to fuzz, so we're giving them more air time. */ + + if (q->exec_us * 0.1 > avg_exec_us) perf_score = 10; + else if (q->exec_us * 0.25 > avg_exec_us) perf_score = 25; + else if (q->exec_us * 0.5 > avg_exec_us) perf_score = 50; + else if (q->exec_us * 0.75 > avg_exec_us) perf_score = 75; + else if (q->exec_us * 4 < avg_exec_us) perf_score = 300; + else if (q->exec_us * 3 < avg_exec_us) perf_score = 200; + else if (q->exec_us * 2 < avg_exec_us) perf_score = 150; + + /* Adjust score based on bitmap size. The working theory is that better + coverage translates to better targets. Multiplier from 0.25x to 3x. */ + + if (q->bitmap_size * 0.3 > avg_bitmap_size) perf_score *= 3; + else if (q->bitmap_size * 0.5 > avg_bitmap_size) perf_score *= 2; + else if (q->bitmap_size * 0.75 > avg_bitmap_size) perf_score *= 1.5; + else if (q->bitmap_size * 3 < avg_bitmap_size) perf_score *= 0.25; + else if (q->bitmap_size * 2 < avg_bitmap_size) perf_score *= 0.5; + else if (q->bitmap_size * 1.5 < avg_bitmap_size) perf_score *= 0.75; + + /* Adjust score based on handicap. Handicap is proportional to how late + in the game we learned about this path. Latecomers are allowed to run + for a bit longer until they catch up with the rest. */ + + if (q->handicap >= 4) { + + perf_score *= 4; + q->handicap -= 4; + + } else if (q->handicap) { + + perf_score *= 2; + q->handicap--; + + } + + /* Final adjustment based on input depth, under the assumption that fuzzing + deeper test cases is more likely to reveal stuff that can't be + discovered with traditional fuzzers. */ + + switch (q->depth) { + + case 0 ... 3: break; + case 4 ... 7: perf_score *= 2; break; + case 8 ... 13: perf_score *= 3; break; + case 14 ... 25: perf_score *= 4; break; + default: perf_score *= 5; + + } + + /* Make sure that we don't go over limit. */ + + if (perf_score > HAVOC_MAX_MULT * 100) perf_score = HAVOC_MAX_MULT * 100; + + return perf_score; + +} + + +/* Helper function to see if a particular change (xor_val = old ^ new) could + be a product of deterministic bit flips with the lengths and stepovers + attempted by afl-fuzz. This is used to avoid dupes in some of the + deterministic fuzzing operations that follow bit flips. We also + return 1 if xor_val is zero, which implies that the old and attempted new + values are identical and the exec would be a waste of time. */ + +static u8 could_be_bitflip(u32 xor_val) { + + u32 sh = 0; + + if (!xor_val) return 1; + + /* Shift left until first bit set. */ + + while (!(xor_val & 1)) { sh++; xor_val >>= 1; } + + /* 1-, 2-, and 4-bit patterns are OK anywhere. */ + + if (xor_val == 1 || xor_val == 3 || xor_val == 15) return 1; + + /* 8-, 16-, and 32-bit patterns are OK only if shift factor is + divisible by 8, since that's the stepover for these ops. */ + + if (sh & 7) return 0; + + if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) + return 1; + + return 0; + +} + + +/* Helper function to see if a particular value is reachable through + arithmetic operations. Used for similar purposes. */ + +static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { + + u32 i, ov = 0, nv = 0, diffs = 0; + + if (old_val == new_val) return 1; + + /* See if one-byte adjustments to any byte could produce this result. */ + + for (i = 0; i < blen; i++) { + + u8 a = old_val >> (8 * i), + b = new_val >> (8 * i); + + if (a != b) { diffs++; ov = a; nv = b; } + + } + + /* If only one byte differs and the values are within range, return 1. */ + + if (diffs == 1) { + + if ((u8)(ov - nv) <= ARITH_MAX || + (u8)(nv - ov) <= ARITH_MAX) return 1; + + } + + if (blen == 1) return 0; + + /* See if two-byte adjustments to any byte would produce this result. */ + + diffs = 0; + + for (i = 0; i < blen / 2; i++) { + + u16 a = old_val >> (16 * i), + b = new_val >> (16 * i); + + if (a != b) { diffs++; ov = a; nv = b; } + + } + + /* If only one word differs and the values are within range, return 1. */ + + if (diffs == 1) { + + if ((u16)(ov - nv) <= ARITH_MAX || + (u16)(nv - ov) <= ARITH_MAX) return 1; + + ov = SWAP16(ov); nv = SWAP16(nv); + + if ((u16)(ov - nv) <= ARITH_MAX || + (u16)(nv - ov) <= ARITH_MAX) return 1; + + } + + /* Finally, let's do the same thing for dwords. */ + + if (blen == 4) { + + if ((u32)(old_val - new_val) <= ARITH_MAX || + (u32)(new_val - old_val) <= ARITH_MAX) return 1; + + new_val = SWAP32(new_val); + old_val = SWAP32(old_val); + + if ((u32)(old_val - new_val) <= ARITH_MAX || + (u32)(new_val - old_val) <= ARITH_MAX) return 1; + + } + + return 0; + +} + + + +/* Last but not least, a similar helper to see if insertion of an + interesting integer is redundant given the insertions done for + shorter blen. The last param (check_le) is set if the caller + already executed LE insertion for current blen and wants to see + if BE variant passed in new_val is unique. */ + +static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { + + u32 i, j; + + if (old_val == new_val) return 1; + + /* See if one-byte insertions from interesting_8 over old_val could + produce new_val. */ + + for (i = 0; i < blen; i++) { + + for (j = 0; j < sizeof(interesting_8); j++) { + + u32 tval = (old_val & ~(0xff << (i * 8))) | + (((u8)interesting_8[j]) << (i * 8)); + + if (new_val == tval) return 1; + + } + + } + + /* Bail out unless we're also asked to examine two-byte LE insertions + as a preparation for BE attempts. */ + + if (blen == 2 && !check_le) return 0; + + /* See if two-byte insertions over old_val could give us new_val. */ + + for (i = 0; i < blen - 1; i++) { + + for (j = 0; j < sizeof(interesting_16) / 2; j++) { + + u32 tval = (old_val & ~(0xffff << (i * 8))) | + (((u16)interesting_16[j]) << (i * 8)); + + if (new_val == tval) return 1; + + /* Continue here only if blen > 2. */ + + if (blen > 2) { + + tval = (old_val & ~(0xffff << (i * 8))) | + (SWAP16(interesting_16[j]) << (i * 8)); + + if (new_val == tval) return 1; + + } + + } + + } + + if (blen == 4 && check_le) { + + /* See if four-byte insertions could produce the same result + (LE only). */ + + for (j = 0; j < sizeof(interesting_32) / 4; j++) + if (new_val == (u32)interesting_32[j]) return 1; + + } + + return 0; + +} + + +/* Take the current entry from the queue, fuzz it for a while. This + function is a tad too long... returns 0 if fuzzed successfully, 1 if + skipped or bailed out. */ +//vector ir_set; + +static u8 fuzz_one(char** argv) { + + s32 len, fd, temp_len, i, j; + u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; + u64 havoc_queued, orig_hit_cnt, new_hit_cnt; + u32 splice_cycle = 0, perf_score = 100, orig_perf, prev_cksum, eff_cnt = 1; + u8 ret_val = 1, doing_det = 0; + + u8 a_collect[MAX_AUTO_EXTRA]; + u32 a_len = 0; + + int skip_count = 0; + +#ifdef IGNORE_FINDS + + /* In IGNORE_FINDS mode, skip any entries that weren't in the + initial data set. */ + + if (queue_cur->depth > 1) return 1; + +#else + + if (pending_favored) { + + /* If we have any favored, non-fuzzed new arrivals in the queue, + possibly skip to them at the expense of already-fuzzed or non-favored + cases. */ + + if ((queue_cur->was_fuzzed || !queue_cur->favored) && + UR(100) < SKIP_TO_NEW_PROB) return 1; + + } else if (!dumb_mode && !queue_cur->favored && queued_paths > 10) { + + /* Otherwise, still possibly skip non-favored cases, albeit less often. + The odds of skipping stuff are higher for already-fuzzed inputs and + lower for never-fuzzed entries. */ + + if (queue_cycle > 1 && !queue_cur->was_fuzzed) { + + if (UR(100) < SKIP_NFAV_NEW_PROB) return 1; + + } else { + + if (UR(100) < SKIP_NFAV_OLD_PROB) return 1; + + } + + } + +#endif /* ^IGNORE_FINDS */ + + if (not_on_tty) { + ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", + current_entry, queued_paths, unique_crashes); + fflush(stdout); + } + + /* Map the test case into memory. */ + + fd = open(queue_cur->fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", queue_cur->fname); + + len = queue_cur->len; + + orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + + if (orig_in == MAP_FAILED) PFATAL("Unable to mmap '%s'", queue_cur->fname); + + close(fd); + + out_buf = ck_alloc_nozero(len+1); + + subseq_tmouts = 0; + + cur_depth = queue_cur->depth; + + memcpy(out_buf, in_buf, len); + out_buf[len] = 0; + + orig_perf = perf_score = calculate_score(queue_cur); + + doing_det = 1; + + stage_short = "SQL fuzz"; + stage_max = len << 3; + stage_name = "fuzzing"; + + stage_val_type = STAGE_VAL_NONE; + + orig_hit_cnt = queued_paths + unique_crashes; + + prev_cksum = queue_cur->exec_cksum; + + seed_count++; + + //********************** + + vector mutated_tree = g_mutator.mutate_all((const char*)out_buf); + + stage_max = mutated_tree.size(); + stage_cur = 0; + + for(InputInfo* input: mutated_tree){ + stage_name = "sql_validate"; + + u8* fn = alloc_printf("%s/crash_input", out_dir); + s32 fd; + FILE* f; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + + f = fdopen(fd, "w"); + + if (!f) PFATAL("fdopen() failed"); + + fprintf(f, "%s\n", input->input_->to_string().c_str()); + + fclose(f); + + bool tmp_res = g_instantiator.instantaite_sql(input->input_); + + if( tmp_res == false){ + skip_count ++ ; + continue; + } + show_stats(); + string ir_str = input->input_->to_string(); + g_current_input = input; + + char* tmp_str = ir_str.c_str(); + int siz = ir_str.size(); + + stage_name = "sql_fuzz"; + if(common_fuzz_stuff(argv, tmp_str, siz)){ + goto abandon_entry; + } + stage_cur++; + show_stats(); + } + + //********************** + + stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; + stage_cycles[STAGE_FLIP1] += mutated_tree.size() - skip_count; + + + new_hit_cnt = queued_paths + unique_crashes; + + ret_val = 0; + +abandon_entry: + for(InputInfo* input: mutated_tree){ + delete input; + } + + + splicing_with = -1; + + /* Update pending_not_fuzzed count if we made it through the calibration + cycle and have not seen this entry before. */ + + if (!stop_soon && !queue_cur->cal_failed && !queue_cur->was_fuzzed) { + queue_cur->was_fuzzed = 1; + pending_not_fuzzed--; + if (queue_cur->favored) pending_favored--; + } + + munmap(orig_in, queue_cur->len); + + + if (in_buf != orig_in){ ck_free(in_buf);} + + ck_free(out_buf); + ck_free(eff_map); + //ir_set.clear(); + + return ret_val; +} + + +/* Grab interesting test cases from other fuzzers. */ + +static void sync_fuzzers(char** argv) { + + DIR* sd; + struct dirent* sd_ent; + u32 sync_cnt = 0; + + sd = opendir(sync_dir); + if (!sd) PFATAL("Unable to open '%s'", sync_dir); + + stage_max = stage_cur = 0; + cur_depth = 0; + + /* Look at the entries created for every other fuzzer in the sync directory. */ + + while ((sd_ent = readdir(sd))) { + + static u8 stage_tmp[128]; + + DIR* qd; + struct dirent* qd_ent; + u8 *qd_path, *qd_synced_path; + u32 min_accept = 0, next_min_accept; + + s32 id_fd; + + /* Skip dot files and our own output directory. */ + + if (sd_ent->d_name[0] == '.' || !strcmp(sync_id, sd_ent->d_name)) continue; + + /* Skip anything that doesn't have a queue/ subdirectory. */ + + qd_path = alloc_printf("%s/%s/queue", sync_dir, sd_ent->d_name); + + if (!(qd = opendir(qd_path))) { + ck_free(qd_path); + continue; + } + + /* Retrieve the ID of the last seen test case. */ + + qd_synced_path = alloc_printf("%s/.synced/%s", out_dir, sd_ent->d_name); + + id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); + + if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path); + + if (read(id_fd, &min_accept, sizeof(u32)) > 0) + lseek(id_fd, 0, SEEK_SET); + + next_min_accept = min_accept; + + /* Show stats */ + + sprintf(stage_tmp, "sync %u", ++sync_cnt); + stage_name = stage_tmp; + stage_cur = 0; + stage_max = 0; + + /* For every file queued by this fuzzer, parse ID and see if we have looked at + it before; exec a test case if not. */ + + while ((qd_ent = readdir(qd))) { + + u8* path; + s32 fd; + struct stat st; + + if (qd_ent->d_name[0] == '.' || + sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &syncing_case) != 1 || + syncing_case < min_accept) continue; + + /* OK, sounds like a new one. Let's give it a try. */ + + if (syncing_case >= next_min_accept) + next_min_accept = syncing_case + 1; + + path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); + + /* Allow this to fail in case the other fuzzer is resuming or so... */ + + fd = open(path, O_RDONLY); + + if (fd < 0) { + ck_free(path); + continue; + } + + if (fstat(fd, &st)) PFATAL("fstat() failed"); + + /* Ignore zero-sized or oversized files. */ + + if (st.st_size && st.st_size <= MAX_FILE) { + + u8 fault; + u8* mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + + if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path); + + /* See what happens. We rely on save_if_interesting() to catch major + errors and save the test case. */ + + write_to_testcase(mem, st.st_size); + + fault = run_target(argv, exec_tmout); + + if (stop_soon) return; + + syncing_party = sd_ent->d_name; + queued_imported += save_if_interesting(argv, mem, st.st_size, fault); + syncing_party = 0; + + munmap(mem, st.st_size); + + if (!(stage_cur++ % stats_update_freq)) show_stats(); + + } + + ck_free(path); + close(fd); + + } + + ck_write(id_fd, &next_min_accept, sizeof(u32), qd_synced_path); + + close(id_fd); + closedir(qd); + ck_free(qd_path); + ck_free(qd_synced_path); + + } + + closedir(sd); + +} + + +/* Handle stop signal (Ctrl-C, etc). */ + +static void handle_stop_sig(int sig) { + + stop_soon = 1; + + if (child_pid > 0) kill(child_pid, SIGKILL); + if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); + +} + + +/* Handle skip request (SIGUSR1). */ + +static void handle_skipreq(int sig) { + + skip_requested = 1; + +} + +/* Handle timeout (SIGALRM). */ + +static void handle_timeout(int sig) { + + if (child_pid > 0) { + + child_timed_out = 1; + kill(child_pid, SIGKILL); + + } else if (child_pid == -1 && forksrv_pid > 0) { + + child_timed_out = 1; + kill(forksrv_pid, SIGKILL); + + } + +} + + +/* Do a PATH search and find target binary to see that it exists and + isn't a shell script - a common and painful mistake. We also check for + a valid ELF header and for evidence of AFL instrumentation. */ + +EXP_ST void check_binary(u8* fname) { + + u8* env_path = 0; + struct stat st; + + s32 fd; + u8* f_data; + u32 f_len = 0; + + ACTF("Validating target binary..."); + + if (strchr((char *)fname, '/') || !(env_path = getenv("PATH"))) { + + target_path = ck_strdup(fname); + if (stat(target_path, &st) || !S_ISREG(st.st_mode) || + !(st.st_mode & 0111) || (f_len = st.st_size) < 4) + FATAL("Program '%s' not found or not executable", fname); + + } else { + + while (env_path) { + + u8 *cur_elem, *delim = strchr((char *)env_path, ':'); + + if (delim) { + + cur_elem = ck_alloc(delim - env_path + 1); + memcpy(cur_elem, env_path, delim - env_path); + delim++; + + } else cur_elem = ck_strdup(env_path); + + env_path = delim; + + if (cur_elem[0]) + target_path = alloc_printf("%s/%s", cur_elem, fname); + else + target_path = ck_strdup(fname); + + ck_free(cur_elem); + + if (!stat(target_path, &st) && S_ISREG(st.st_mode) && + (st.st_mode & 0111) && (f_len = st.st_size) >= 4) break; + + ck_free(target_path); + target_path = 0; + + } + + if (!target_path) FATAL("Program '%s' not found or not executable", fname); + + } + + if (getenv("AFL_SKIP_BIN_CHECK")) return; + + /* Check for blatant user errors. */ + + if ((!strncmp(target_path, "/tmp/", 5) && !strchr((char *)target_path + 5, '/')) || + (!strncmp(target_path, "/var/tmp/", 9) && !strchr((char *)target_path + 9, '/'))) + FATAL("Please don't keep binaries in /tmp or /var/tmp"); + + fd = open(target_path, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", target_path); + + f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + + if (f_data == MAP_FAILED) PFATAL("Unable to mmap file '%s'", target_path); + + close(fd); + + if (f_data[0] == '#' && f_data[1] == '!') { + + SAYF("\n" cLRD "[-] " cRST + "Oops, the target binary looks like a shell script. Some build systems will\n" + " sometimes generate shell stubs for dynamically linked programs; try static\n" + " library mode (./configure --disable-shared) if that's the case.\n\n" + + " Another possible cause is that you are actually trying to use a shell\n" + " wrapper around the fuzzed component. Invoking shell can slow down the\n" + " fuzzing process by a factor of 20x or more; it's best to write the wrapper\n" + " in a compiled language instead.\n"); + + FATAL("Program '%s' is a shell script", target_path); + + } + +#ifndef __APPLE__ + + if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) + FATAL("Program '%s' is not an ELF binary", target_path); + +#else + + if (f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) + FATAL("Program '%s' is not a 64-bit Mach-O binary", target_path); + +#endif /* ^!__APPLE__ */ + + if (!qemu_mode && !dumb_mode && + !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { + + SAYF("\n" cLRD "[-] " cRST + "Looks like the target binary is not instrumented! The fuzzer depends on\n" + " compile-time instrumentation to isolate interesting test cases while\n" + " mutating the input data. For more information, and for tips on how to\n" + " instrument binaries, please see %s/README.\n\n" + + " When source code is not available, you may be able to leverage QEMU\n" + " mode support. Consult the README for tips on how to enable this.\n" + + " (It is also possible to use afl-fuzz as a traditional, \"dumb\" fuzzer.\n" + " For that, you can use the -n option - but expect much worse results.)\n", + doc_path); + + FATAL("No instrumentation detected"); + + } + + if (qemu_mode && + memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { + + SAYF("\n" cLRD "[-] " cRST + "This program appears to be instrumented with afl-gcc, but is being run in\n" + " QEMU mode (-Q). This is probably not what you want - this setup will be\n" + " slow and offer no practical benefits.\n"); + + FATAL("Instrumentation found in -Q mode"); + + } + + if (memmem(f_data, f_len, "libasan.so", 10) || + memmem(f_data, f_len, "__msan_init", 11)) uses_asan = 1; + + /* Detect persistent & deferred init signatures in the binary. */ + + if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { + + OKF(cPIN "Persistent mode binary detected."); + setenv(PERSIST_ENV_VAR, "1", 1); + persistent_mode = 1; + + } else if (getenv("AFL_PERSISTENT")) { + + WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); + + } + + if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { + + OKF(cPIN "Deferred forkserver binary detected."); + setenv(DEFER_ENV_VAR, "1", 1); + deferred_mode = 1; + + } else if (getenv("AFL_DEFER_FORKSRV")) { + + WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); + + } + + if (munmap(f_data, f_len)) PFATAL("unmap() failed"); + +} + + +/* Trim and possibly create a banner for the run. */ + +static void fix_up_banner(u8* name) { + + if (!use_banner) { + + if (sync_id) { + + use_banner = sync_id; + + } else { + + u8* trim = strrchr((const char*)name, '/'); + if (!trim) use_banner = name; else use_banner = trim + 1; + + } + + } + + if (strlen(use_banner) > 40) { + + u8* tmp = ck_alloc(44); + sprintf(tmp, "%.40s...", use_banner); + use_banner = tmp; + + } + +} + + +/* Check if we're on TTY. */ + +static void check_if_tty(void) { + + struct winsize ws; + + if (getenv("AFL_NO_UI")) { + OKF("Disabling the UI because AFL_NO_UI is set."); + not_on_tty = 1; + return; + } + + if (ioctl(1, TIOCGWINSZ, &ws)) { + + if (errno == ENOTTY) { + OKF("Looks like we're not running on a tty, so I'll be a bit less verbose."); + not_on_tty = 1; + } + + return; + } + +} + + +/* Check terminal dimensions after resize. */ + +static void check_term_size(void) { + + struct winsize ws; + + term_too_small = 0; + + if (ioctl(1, TIOCGWINSZ, &ws)) return; + + if (ws.ws_row < 25 || ws.ws_col < 80) term_too_small = 1; + +} + + + +/* Display usage hints. */ + +static void usage(u8* argv0) { + + SAYF("\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n" + + "Required parameters:\n\n" + + " -i dir - input directory with test cases\n" + " -o dir - output directory for fuzzer findings\n\n" + + "Execution control settings:\n\n" + + " -f file - location read by the fuzzed program (stdin)\n" + " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" + " -m megs - memory limit for child process (%u MB)\n" + " -Q - use binary-only instrumentation (QEMU mode)\n\n" + + "Fuzzing behavior settings:\n\n" + + " -d - quick & dirty mode (skips deterministic steps)\n" + " -n - fuzz without instrumentation (dumb mode)\n" + " -x dir - optional fuzzer dictionary (see README)\n\n" + + "Other stuff:\n\n" + + " -T text - text banner to show on the screen\n" + " -M / -S id - distributed mode (see parallel_fuzzing.txt)\n" + " -C - crash exploration mode (the peruvian rabbit thing)\n\n" + + "For additional tips, please consult %s/README.\n\n", + + argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); + + exit(1); + +} + + +/* Prepare output directories and fds. */ + +EXP_ST void setup_dirs_fds(void) { + + u8* tmp; + s32 fd; + + ACTF("Setting up output directories..."); + + if (sync_id && mkdir(sync_dir, 0700) && errno != EEXIST) + PFATAL("Unable to create '%s'", sync_dir); + + if (mkdir(out_dir, 0700)) { + + if (errno != EEXIST) PFATAL("Unable to create '%s'", out_dir); + + maybe_delete_out_dir(); + + } else { + + if (in_place_resume) + FATAL("Resume attempted but old output directory not found"); + + out_dir_fd = open(out_dir, O_RDONLY); + +#ifndef __sun + + if (out_dir_fd < 0 || flock(out_dir_fd, LOCK_EX | LOCK_NB)) + PFATAL("Unable to flock() output directory."); + +#endif /* !__sun */ + + } + + /* Queue directory for any starting & discovered paths. */ + + tmp = alloc_printf("%s/queue", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Top-level directory for queue metadata used for session + resume and related tasks. */ + + tmp = alloc_printf("%s/queue/.state/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Directory for flagging queue entries that went through + deterministic fuzzing in the past. */ + + tmp = alloc_printf("%s/queue/.state/deterministic_done/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Directory with the auto-selected dictionary entries. */ + + tmp = alloc_printf("%s/queue/.state/auto_extras/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* The set of paths currently deemed redundant. */ + + tmp = alloc_printf("%s/queue/.state/redundant_edges/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* The set of paths showing variable behavior. */ + + tmp = alloc_printf("%s/queue/.state/variable_behavior/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Sync directory for keeping track of cooperating fuzzers. */ + + if (sync_id) { + + tmp = alloc_printf("%s/.synced/", out_dir); + + if (mkdir(tmp, 0700) && (!in_place_resume || errno != EEXIST)) + PFATAL("Unable to create '%s'", tmp); + + ck_free(tmp); + + } + + /* All recorded crashes. */ + + tmp = alloc_printf("%s/crashes", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* All recorded hangs. */ + + tmp = alloc_printf("%s/hangs", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Generally useful file descriptors. */ + + dev_null_fd = open("/dev/null", O_RDWR); + if (dev_null_fd < 0) PFATAL("Unable to open /dev/null"); + + dev_urandom_fd = open("/dev/urandom", O_RDONLY); + if (dev_urandom_fd < 0) PFATAL("Unable to open /dev/urandom"); + + /* Gnuplot output file. */ + + tmp = alloc_printf("%s/plot_data", out_dir); + fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + plot_file = fdopen(fd, "w"); + if (!plot_file) PFATAL("fdopen() failed"); + + fprintf(plot_file, "# unix_time, cycles_done, cur_path, paths_total, " + "pending_total, pending_favs, map_size, unique_crashes, " + "unique_hangs, max_depth, execs_per_sec, total_execs, total_vaild, seed_count\n"); +} + + +/* Setup the output file for fuzzed data, if not using -f. */ + +EXP_ST void setup_stdio_file(void) { + + u8* fn = alloc_printf("%s/.cur_input", out_dir); + + unlink(fn); /* Ignore errors */ + + out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600); + + if (out_fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + +} + + +/* Make sure that core dumps don't go to a program. */ + +static void check_crash_handling(void) { + +#ifdef __APPLE__ + + /* Yuck! There appears to be no simple C API to query for the state of + loaded daemons on MacOS X, and I'm a bit hesitant to do something + more sophisticated, such as disabling crash reporting via Mach ports, + until I get a box to test the code. So, for now, we check for crash + reporting the awful way. */ + + if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return; + + SAYF("\n" cLRD "[-] " cRST + "Whoops, your system is configured to forward crash notifications to an\n" + " external crash reporting utility. This will cause issues due to the\n" + " extended delay between the fuzzed binary malfunctioning and this fact\n" + " being relayed to the fuzzer via the standard waitpid() API.\n\n" + " To avoid having crashes misinterpreted as timeouts, please run the\n" + " following commands:\n\n" + + " SL=/System/Library; PL=com.apple.ReportCrash\n" + " launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n" + " sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n"); + + if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) + FATAL("Crash reporter detected"); + +#else + + /* This is Linux specific, but I don't think there's anything equivalent on + *BSD, so we can just let it slide for now. */ + + s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY); + u8 fchar; + + if (fd < 0) return; + + ACTF("Checking core_pattern..."); + + /*if (read(fd, &fchar, 1) == 1 && fchar == '|') { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, your system is configured to send core dump notifications to an\n" + " external utility. This will cause issues: there will be an extended delay\n" + " between stumbling upon a crash and having this information relayed to the\n" + " fuzzer via the standard waitpid() API.\n\n" + + " To avoid having crashes misinterpreted as timeouts, please log in as root\n" + " and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" + + " echo core >/proc/sys/kernel/core_pattern\n"); + + if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) + FATAL("Pipe at the beginning of 'core_pattern'"); + + }*/ + + close(fd); + +#endif /* ^__APPLE__ */ + +} + + +/* Check CPU governor. */ + +static void check_cpu_governor(void) { + + FILE* f; + u8 tmp[128]; + u64 min = 0, max = 0; + + if (getenv("AFL_SKIP_CPUFREQ")) return; + + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r"); + if (!f) return; + + ACTF("Checking CPU scaling governor..."); + + if (!fgets(tmp, 128, f)) PFATAL("fgets() failed"); + + fclose(f); + + if (!strncmp(tmp, "perf", 4)) return; + + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r"); + + if (f) { + if (fscanf(f, "%llu", &min) != 1) min = 0; + fclose(f); + } + + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r"); + + if (f) { + if (fscanf(f, "%llu", &max) != 1) max = 0; + fclose(f); + } + + if (min == max) return; + + SAYF("\n" cLRD "[-] " cRST + "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" + " between %llu and %llu MHz. Unfortunately, the scaling algorithm in the\n" + " kernel is imperfect and can miss the short-lived processes spawned by\n" + " afl-fuzz. To keep things moving, run these commands as root:\n\n" + + " cd /sys/devices/system/cpu\n" + " echo performance | tee cpu*/cpufreq/scaling_governor\n\n" + + " You can later go back to the original state by replacing 'performance' with\n" + " 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ\n" + " to make afl-fuzz skip this check - but expect some performance drop.\n", + min / 1024, max / 1024); + + FATAL("Suboptimal CPU scaling governor"); + +} + + +/* Count the number of logical CPU cores. */ + +static void get_core_count(void) { + + u32 cur_runnable = 0; + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) + + size_t s = sizeof(cpu_core_count); + + /* On *BSD systems, we can just use a sysctl to get the number of CPUs. */ + +#ifdef __APPLE__ + + if (sysctlbyname("hw.logicalcpu", &cpu_core_count, &s, NULL, 0) < 0) + return; + +#else + + int s_name[2] = { CTL_HW, HW_NCPU }; + + if (sysctl(s_name, 2, &cpu_core_count, &s, NULL, 0) < 0) return; + +#endif /* ^__APPLE__ */ + +#else + +#ifdef HAVE_AFFINITY + + cpu_core_count = sysconf(_SC_NPROCESSORS_ONLN); + +#else + + FILE* f = fopen("/proc/stat", "r"); + u8 tmp[1024]; + + if (!f) return; + + while (fgets(tmp, sizeof(tmp), f)) + if (!strncmp(tmp, "cpu", 3) && isdigit(tmp[3])) cpu_core_count++; + + fclose(f); + +#endif /* ^HAVE_AFFINITY */ + +#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ + + if (cpu_core_count > 0) { + + cur_runnable = (u32)get_runnable_processes(); + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) + + /* Add ourselves, since the 1-minute average doesn't include that yet. */ + + cur_runnable++; + +#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ + + OKF("You have %u CPU core%s and %u runnable tasks (utilization: %0.0f%%).", + cpu_core_count, cpu_core_count > 1 ? "s" : "", + cur_runnable, cur_runnable * 100.0 / cpu_core_count); + + if (cpu_core_count > 1) { + + if (cur_runnable > cpu_core_count * 1.5) { + + WARNF("System under apparent load, performance may be spotty."); + + } else if (cur_runnable + 1 <= cpu_core_count) { + + OKF("Try parallel jobs - see %s/parallel_fuzzing.txt.", doc_path); + + } + + } + + } else { + + cpu_core_count = 0; + WARNF("Unable to figure out the number of CPU cores."); + + } + +} + + +/* Validate and fix up out_dir and sync_dir when using -S. */ + +static void fix_up_sync(void) { + + u8* x = sync_id; + + if (dumb_mode) + FATAL("-S / -M and -n are mutually exclusive"); + + if (skip_deterministic) { + + if (force_deterministic) + FATAL("use -S instead of -M -d"); + else + FATAL("-S already implies -d"); + + } + + while (*x) { + + if (!isalnum(*x) && *x != '_' && *x != '-') + FATAL("Non-alphanumeric fuzzer ID specified via -S or -M"); + + x++; + + } + + if (strlen(sync_id) > 32) FATAL("Fuzzer ID too long"); + + x = alloc_printf("%s/%s", out_dir, sync_id); + + sync_dir = out_dir; + out_dir = x; + + if (!force_deterministic) { + skip_deterministic = 1; + use_splicing = 1; + } + +} + + +/* Handle screen resize (SIGWINCH). */ + +static void handle_resize(int sig) { + clear_screen = 1; +} + + +/* Check ASAN options. */ + +static void check_asan_opts(void) { + u8* x = getenv("ASAN_OPTIONS"); + + if (x) { + + if (!strstr((char *)x, "abort_on_error=1")) + FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); + + if (!strstr((char *)x, "symbolize=0")) + FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); + + } + + x = getenv("MSAN_OPTIONS"); + + if (x) { + + if (!strstr((char *)x, "exit_code=" STRINGIFY(MSAN_ERROR))) + FATAL("Custom MSAN_OPTIONS set without exit_code=" + STRINGIFY(MSAN_ERROR) " - please fix!"); + + if (!strstr((char *)x, "symbolize=0")) + FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); + + } + +} + + +/* Detect @@ in args. */ + +EXP_ST void detect_file_args(char** argv) { + + u32 i = 0; + u8* cwd = getcwd(NULL, 0); + + if (!cwd) PFATAL("getcwd() failed"); + + while (argv[i]) { + + u8* aa_loc = strstr((const char*)argv[i], "@@"); + + if (aa_loc) { + + u8 *aa_subst, *n_arg; + + /* If we don't have a file name chosen yet, use a safe default. */ + + if (!out_file) + out_file = alloc_printf("%s/.cur_input", out_dir); + + /* Be sure that we're always using fully-qualified paths. */ + + if (out_file[0] == '/') aa_subst = out_file; + else aa_subst = alloc_printf("%s/%s", cwd, out_file); + + /* Construct a replacement argv value. */ + + *aa_loc = 0; + n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); + argv[i] = n_arg; + *aa_loc = '@'; + + if (out_file[0] != '/') ck_free(aa_subst); + + } + + i++; + + } + + free(cwd); /* not tracked */ + +} + + +/* Set up signal handlers. More complicated that needs to be, because libc on + Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call + siginterrupt(), and does other unnecessary things. */ + +EXP_ST void setup_signal_handlers(void) { + + struct sigaction sa; + + sa.sa_handler = NULL; + sa.sa_flags = SA_RESTART; + sa.sa_sigaction = NULL; + + sigemptyset(&sa.sa_mask); + + /* Various ways of saying "stop". */ + + sa.sa_handler = handle_stop_sig; + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + /* Exec timeout notifications. */ + + sa.sa_handler = handle_timeout; + sigaction(SIGALRM, &sa, NULL); + + /* Window resize */ + + sa.sa_handler = handle_resize; + sigaction(SIGWINCH, &sa, NULL); + + /* SIGUSR1: skip entry */ + + sa.sa_handler = handle_skipreq; + sigaction(SIGUSR1, &sa, NULL); + + /* Things we don't care about. */ + + sa.sa_handler = SIG_IGN; + sigaction(SIGTSTP, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + +} + + +/* Rewrite argv for QEMU. */ + +static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { + + char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); + u8 *tmp, *cp, *rsl, *own_copy; + + /* Workaround for a QEMU stability glitch. */ + + setenv("QEMU_LOG", "nochain", 1); + + memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); + + new_argv[2] = target_path; + new_argv[1] = "--"; + + /* Now we need to actually find the QEMU binary to put in argv[0]. */ + + tmp = getenv("AFL_PATH"); + + if (tmp) { + + cp = alloc_printf("%s/afl-qemu-trace", tmp); + + if (access(cp, X_OK)) + FATAL("Unable to find '%s'", tmp); + + target_path = new_argv[0] = cp; + return new_argv; + + } + + own_copy = ck_strdup(own_loc); + rsl = strrchr((const char*)own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + cp = alloc_printf("%s/afl-qemu-trace", own_copy); + ck_free(own_copy); + + if (!access(cp, X_OK)) { + + target_path = new_argv[0] = cp; + return new_argv; + + } + + } else ck_free(own_copy); + + if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { + + target_path = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); + return new_argv; + + } + + SAYF("\n" cLRD "[-] " cRST + "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be built\n" + " separately by following the instructions in qemu_mode/README.qemu. If you\n" + " already have the binary installed, you may need to specify AFL_PATH in the\n" + " environment.\n\n" + + " Of course, even without QEMU, afl-fuzz can still work with binaries that are\n" + " instrumented at compile time with afl-gcc. It is also possible to use it as a\n" + " traditional \"dumb\" fuzzer by specifying '-n' in the command line.\n"); + + FATAL("Failed to locate 'afl-qemu-trace'."); + +} + + +/* Make a copy of the current command line. */ + +static void save_cmdline(u32 argc, char** argv) { + + u32 len = 1, i; + u8* buf; + + for (i = 0; i < argc; i++) + len += strlen(argv[i]) + 1; + + buf = orig_cmdline = ck_alloc(len); + + for (i = 0; i < argc; i++) { + + u32 l = strlen(argv[i]); + + memcpy(buf, argv[i], l); + buf += l; + + if (i != argc - 1) *(buf++) = ' '; + + } + + *buf = 0; + +} + +#ifndef AFL_LIB + +char* g_server_path; +char* g_client_path; + +int main(int argc, char** argv) { + s32 opt; + u64 prev_queued = 0; + u32 sync_interval_cnt = 0, seek_to; + u8 *extras_dir = 0; + u8 mem_limit_given = 0; + u8 exit_1 = !!getenv("AFL_BENCH_JUST_ONE"); + char** use_argv; + + struct timeval tv; + struct timezone tz; + memset_fucking_array(); + SAYF(cCYA "SQLFuzzer " cBRI VERSION cRST " by hackers\n");//string_lib he common_string_lib YOUSHENME QUBIE + + doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; + + gettimeofday(&tv, &tz); + srandom(tv.tv_sec ^ tv.tv_usec ^ getpid()); + + while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q:s:c:")) > 0) + + switch (opt) { + case 'i': /* input dir */ + + if (in_dir) FATAL("Multiple -i options not supported"); + in_dir = optarg; + + if (!strcmp(in_dir, "-")) in_place_resume = 1; + + break; + + case 's': /* server's path */ + if (g_server_path) FATAL("Multiple -s options not supported"); + g_server_path = optarg; + break; + + case 'o': /* output dir */ + + if (out_dir) FATAL("Multiple -o options not supported"); + out_dir = optarg; + break; + + case 'M': { /* master sync ID */ + + u8* c; + + if (sync_id) FATAL("Multiple -S or -M options not supported"); + sync_id = ck_strdup(optarg); + + if ((c = strchr((char *)sync_id, ':'))) { + + *c = 0; + + if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 || + !master_id || !master_max || master_id > master_max || + master_max > 1000000) FATAL("Bogus master ID passed to -M"); + + } + + force_deterministic = 1; + + } + + break; + + case 'S': + + if (sync_id) FATAL("Multiple -S or -M options not supported"); + sync_id = ck_strdup(optarg); + break; + + case 'f': /* target file */ + + if (out_file) FATAL("Multiple -f options not supported"); + out_file = optarg; + break; + + case 'x': /* dictionary */ + + if (extras_dir) FATAL("Multiple -x options not supported"); + extras_dir = optarg; + break; + + case 't': { /* timeout */ + + u8 suffix = 0; + + if (timeout_given) FATAL("Multiple -t options not supported"); + + if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 || + optarg[0] == '-') FATAL("Bad syntax used for -t"); + + if (exec_tmout < 5) FATAL("Dangerously low value of -t"); + + if (suffix == '+') timeout_given = 2; else timeout_given = 1; + + break; + + } + + case 'm': { /* mem limit */ + + u8 suffix = 'M'; + + if (mem_limit_given) FATAL("Multiple -m options not supported"); + mem_limit_given = 1; + + if (!strcmp(optarg, "none")) { + + mem_limit = 0; + break; + + } + + if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || + optarg[0] == '-') FATAL("Bad syntax used for -m"); + + switch (suffix) { + + case 'T': mem_limit *= 1024 * 1024; break; + case 'G': mem_limit *= 1024; break; + case 'k': mem_limit /= 1024; break; + case 'M': break; + + default: FATAL("Unsupported suffix or bad syntax for -m"); + + } + + if (mem_limit < 5) FATAL("Dangerously low value of -m"); + + if (sizeof(rlim_t) == 4 && mem_limit > 2000) + FATAL("Value of -m out of range on 32-bit systems"); + + } + + break; + + case 'd': /* skip deterministic */ + + if (skip_deterministic) FATAL("Multiple -d options not supported"); + skip_deterministic = 1; + use_splicing = 1; + break; + + case 'B': /* load bitmap */ + + /* This is a secret undocumented option! It is useful if you find + an interesting test case during a normal fuzzing process, and want + to mutate it without rediscovering any of the test cases already + found during an earlier run. + + To use this mode, you need to point -B to the fuzz_bitmap produced + by an earlier run for the exact same binary... and that's it. + + I only used this once or twice to get variants of a particular + file, so I'm not making this an official setting. */ + + if (in_bitmap) FATAL("Multiple -B options not supported"); + + in_bitmap = optarg; + read_bitmap(in_bitmap); + break; + + case 'C': /* crash mode */ + + if (crash_mode) FATAL("Multiple -C options not supported"); + crash_mode = FAULT_CRASH; + break; + + case 'n': /* dumb mode */ + + if (dumb_mode) FATAL("Multiple -n options not supported"); + if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1; + + break; + + case 'T': /* banner */ + + if (use_banner) FATAL("Multiple -T options not supported"); + use_banner = optarg; + break; + + case 'Q': /* QEMU mode */ + + if (qemu_mode) FATAL("Multiple -Q options not supported"); + qemu_mode = 1; + + if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; + + break; + + default: + + usage(argv[0]); + + } + + if (optind == argc || !in_dir || !out_dir) usage(argv[0]); + + setup_signal_handlers(); + check_asan_opts(); + + if (sync_id) fix_up_sync(); + + if (!strcmp(in_dir, out_dir)) + FATAL("Input and output directories can't be the same"); + + if (dumb_mode) { + + if (crash_mode) FATAL("-C and -n are mutually exclusive"); + if (qemu_mode) FATAL("-Q and -n are mutually exclusive"); + + } + + no_forkserver = 1; + if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1; + if (getenv("AFL_NO_ARITH")) no_arith = 1; + if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1; + if (getenv("AFL_FAST_CAL")) fast_cal = 1; + + if (getenv("AFL_HANG_TMOUT")) { + hang_tmout = atoi(getenv("AFL_HANG_TMOUT")); + if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); + } + + if (dumb_mode == 2 && no_forkserver) + FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); + + if (getenv("AFL_PRELOAD")) { + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); + setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); + } + + if (getenv("AFL_LD_PRELOAD")) + FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); + + save_cmdline(argc, argv); + + fix_up_banner(argv[optind]); + + check_if_tty(); + + get_core_count(); + + #ifdef HAVE_AFFINITY + bind_to_free_cpu(); + #endif /* HAVE_AFFINITY */ + //check_crash_handling(); + check_cpu_governor(); + + setup_post(); + setup_shm(); + init_count_class16(); + + setup_dirs_fds(); + read_testcases(); + load_auto(); + + pivot_inputs(); + + if (extras_dir) load_extras(extras_dir); + + if (!timeout_given) find_timeout(); + + detect_file_args(argv + optind + 1); + + if (!out_file) setup_stdio_file(); + + //check_binary(argv[optind]); + //check_binary(g_server_path); + + start_time = get_cur_time(); + last_save_time = start_time; + + if (qemu_mode) + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + else + use_argv = argv + optind; + + g_mutator.init_IR_library(INIT_LIB); + g_mutator.init_IR_config_info(GRAMMAR_INFORMATION); + + g_connector.close_db(); + g_connector.start_db(file, options); + + //char* tmp_argv[] = {g_server_path, NULL}; + //init_forkserver(tmp_argv); + // to do + perform_dry_run(use_argv); + + cull_queue(); + + show_init_stats(); + + seek_to = find_start_position(); + + write_stats_file(0, 0, 0); + save_auto(); + + if (stop_soon) goto stop_fuzzing; + + /* Woop woop woop */ + + if (!not_on_tty) { + sleep(4); + start_time += 4000; + if (stop_soon) goto stop_fuzzing; + } + + //reboot_server(0x1000000);//start server before we fuzz + while (1) { + + u8 skipped_fuzz; + + cull_queue(); + + if (!queue_cur) { + + queue_cycle++; + current_entry = 0; + cur_skipped_paths = 0; + queue_cur = queue; + + while (seek_to) { + current_entry++; + seek_to--; + queue_cur = queue_cur->next; + } + + show_stats(); + + if (not_on_tty) { + ACTF("Entering queue cycle %llu.", queue_cycle); + fflush(stdout); + } + + /* If we had a full queue cycle with no new finds, try + recombination strategies next. */ + + if (queued_paths == prev_queued) { + + if (use_splicing) cycles_wo_finds++; else use_splicing = 1; + + } else cycles_wo_finds = 0; + + prev_queued = queued_paths; + + if (sync_id && queue_cycle == 1 && getenv("AFL_IMPORT_FIRST")) + sync_fuzzers(use_argv); + + } + + skipped_fuzz = fuzz_one(use_argv); + + if (!stop_soon && sync_id && !skipped_fuzz) { + + if (!(sync_interval_cnt++ % SYNC_INTERVAL)) + sync_fuzzers(use_argv); + + } + + if (!stop_soon && exit_1) stop_soon = 2; + + if (stop_soon) break; + + queue_cur = queue_cur->next; + current_entry++; + } + + if (queue_cur) show_stats(); + + write_bitmap(); + write_stats_file(0, 0, 0); + save_auto(); + +stop_fuzzing: + + SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, + stop_soon == 2 ? "programmatically" : "by user"); + + /* Running for more than 30 minutes but still doing first cycle? */ + + if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) { + + SAYF("\n" cYEL "[!] " cRST + "Stopped during the first cycle, results may be incomplete.\n" + " (For info on resuming, see %s/README.)\n", doc_path); + + } + + //g_mutator.print_information(OUTPUT_PATH); + g_connector.close_db(); + + fclose(plot_file); + destroy_queue(); + destroy_extras(); + ck_free(target_path); + ck_free(sync_id); + + alloc_report(); + + OKF("We're done here. Have a nice day!\n"); + + exit(0); + +} + +#endif /* !AFL_LIB */ diff --git a/AFL/alloc-inl.h b/AFL/alloc-inl.h new file mode 100755 index 0000000..9a68126 --- /dev/null +++ b/AFL/alloc-inl.h @@ -0,0 +1,577 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - error-checking, memory-zeroing alloc routines + ------------------------------------------------------------------ + + Written and maintained by Michal Zalewski + + This allocator is not designed to resist malicious attackers (the canaries + are small and predictable), but provides a robust and portable way to detect + use-after-free, off-by-one writes, stale pointers, and so on. +*/ + +#ifndef _HAVE_ALLOC_INL_H +#define _HAVE_ALLOC_INL_H + +#include +#include +#include + +#include "config.h" +#include "types.h" +#include "debug.h" + +/* User-facing macro to sprintf() to a dynamically allocated buffer. */ + +#define alloc_printf(_str...) ({ \ + u8* _tmp; \ + s32 _len = snprintf(NULL, 0, _str); \ + if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \ + _tmp = ck_alloc(_len + 1); \ + snprintf((char*)_tmp, _len + 1, _str); \ + _tmp; \ + }) + +/* Macro to enforce allocation limits as a last-resort defense against + integer overflows. */ + +#define ALLOC_CHECK_SIZE(_s) do { \ + if ((_s) > MAX_ALLOC) \ + ABORT("Bad alloc request: %u bytes", (_s)); \ + } while (0) + +/* Macro to check malloc() failures and the like. */ + +#define ALLOC_CHECK_RESULT(_r, _s) do { \ + if (!(_r)) \ + ABORT("Out of memory: can't allocate %u bytes", (_s)); \ + } while (0) + +/* Magic tokens used to mark used / freed chunks. */ + +#define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ +#define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ +#define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */ + +/* Positions of guard tokens in relation to the user-visible pointer. */ + +#define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) +#define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) +#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) + +#define ALLOC_OFF_HEAD 8 +#define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) + +/* Allocator increments for ck_realloc_block(). */ + +#define ALLOC_BLK_INC 256 + +/* Sanity-checking macros for pointers. */ + +#define CHECK_PTR(_p) do { \ + if (_p) { \ + if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ + if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ + ABORT("Use after free."); \ + else ABORT("Corrupted head alloc canary."); \ + } \ + if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ + ABORT("Corrupted tail alloc canary."); \ + } \ + } while (0) + +#define CHECK_PTR_EXPR(_p) ({ \ + typeof (_p) _tmp = (_p); \ + CHECK_PTR(_tmp); \ + _tmp; \ + }) + + +/* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized + requests. */ + +static inline void* DFL_ck_alloc_nozero(u32 size) { + + void* ret; + + if (!size) return NULL; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + return ret; + +} + + +/* Allocate a buffer, returning zeroed memory. */ + +static inline void* DFL_ck_alloc(u32 size) { + + void* mem; + + if (!size) return NULL; + mem = DFL_ck_alloc_nozero(size); + + return memset(mem, 0, size); + +} + + +/* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD + is set, the old memory will be also clobbered with 0xFF. */ + +static inline void DFL_ck_free(void* mem) { + + if (!mem) return; + + CHECK_PTR(mem); + +#ifdef DEBUG_BUILD + + /* Catch pointer issues sooner. */ + memset(mem, 0xFF, ALLOC_S(mem)); + +#endif /* DEBUG_BUILD */ + + ALLOC_C1(mem) = ALLOC_MAGIC_F; + + free(mem - ALLOC_OFF_HEAD); + +} + + +/* Re-allocate a buffer, checking for issues and zeroing any newly-added tail. + With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the + old memory is clobbered with 0xFF. */ + +static inline void* DFL_ck_realloc(void* orig, u32 size) { + + void* ret; + u32 old_size = 0; + + if (!size) { + + DFL_ck_free(orig); + return NULL; + + } + + if (orig) { + + CHECK_PTR(orig); + +#ifndef DEBUG_BUILD + ALLOC_C1(orig) = ALLOC_MAGIC_F; +#endif /* !DEBUG_BUILD */ + + old_size = ALLOC_S(orig); + orig -= ALLOC_OFF_HEAD; + + ALLOC_CHECK_SIZE(old_size); + + } + + ALLOC_CHECK_SIZE(size); + +#ifndef DEBUG_BUILD + + ret = realloc(orig, size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + +#else + + /* Catch pointer issues sooner: force relocation and make sure that the + original buffer is wiped. */ + + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + if (orig) { + + memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); + memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); + + ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; + + free(orig); + + } + +#endif /* ^!DEBUG_BUILD */ + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + if (size > old_size) + memset(ret + old_size, 0, size - old_size); + + return ret; + +} + + +/* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up + repeated small reallocs without complicating the user code). */ + +static inline void* DFL_ck_realloc_block(void* orig, u32 size) { + +#ifndef DEBUG_BUILD + + if (orig) { + + CHECK_PTR(orig); + + if (ALLOC_S(orig) >= size) return orig; + + size += ALLOC_BLK_INC; + + } + +#endif /* !DEBUG_BUILD */ + + return DFL_ck_realloc(orig, size); + +} + + +/* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */ + +static inline u8* DFL_ck_strdup(u8* str) { + + void* ret; + u32 size; + + if (!str) return NULL; + + size = strlen((char*)str) + 1; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + return memcpy(ret, str, size); + +} + + +/* Create a buffer with a copy of a memory block. Returns NULL for zero-sized + or NULL inputs. */ + +static inline void* DFL_ck_memdup(void* mem, u32 size) { + + void* ret; + + if (!mem || !size) return NULL; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + return memcpy(ret, mem, size); + +} + + +/* Create a buffer with a block of text, appending a NUL terminator at the end. + Returns NULL for zero-sized or NULL inputs. */ + +static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { + + u8* ret; + + if (!mem || !size) return NULL; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL + 1); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + memcpy(ret, mem, size); + ret[size] = 0; + + return ret; + +} + + +#ifndef DEBUG_BUILD + +/* In non-debug mode, we just do straightforward aliasing of the above functions + to user-visible names such as ck_alloc(). */ + +#define ck_alloc DFL_ck_alloc +#define ck_alloc_nozero DFL_ck_alloc_nozero +#define ck_realloc DFL_ck_realloc +#define ck_realloc_block DFL_ck_realloc_block +#define ck_strdup DFL_ck_strdup +#define ck_memdup DFL_ck_memdup +#define ck_memdup_str DFL_ck_memdup_str +#define ck_free DFL_ck_free + +#define alloc_report() + +#else + +/* In debugging mode, we also track allocations to detect memory leaks, and the + flow goes through one more layer of indirection. */ + +/* Alloc tracking data structures: */ + +#define ALLOC_BUCKETS 4096 + +struct TRK_obj { + void *ptr; + char *file, *func; + u32 line; +}; + +#ifdef AFL_MAIN + +struct TRK_obj* TRK[ALLOC_BUCKETS]; +u32 TRK_cnt[ALLOC_BUCKETS]; + +# define alloc_report() TRK_report() + +#else + +extern struct TRK_obj* TRK[ALLOC_BUCKETS]; +extern u32 TRK_cnt[ALLOC_BUCKETS]; + +# define alloc_report() + +#endif /* ^AFL_MAIN */ + +/* Bucket-assigning function for a given pointer: */ + +#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) + + +/* Add a new entry to the list of allocated objects. */ + +static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, + u32 line) { + + u32 i, bucket; + + if (!ptr) return; + + bucket = TRKH(ptr); + + /* Find a free slot in the list of entries for that bucket. */ + + for (i = 0; i < TRK_cnt[bucket]; i++) + + if (!TRK[bucket][i].ptr) { + + TRK[bucket][i].ptr = ptr; + TRK[bucket][i].file = (char*)file; + TRK[bucket][i].func = (char*)func; + TRK[bucket][i].line = line; + return; + + } + + /* No space available - allocate more. */ + + TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], + (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); + + TRK[bucket][i].ptr = ptr; + TRK[bucket][i].file = (char*)file; + TRK[bucket][i].func = (char*)func; + TRK[bucket][i].line = line; + + TRK_cnt[bucket]++; + +} + + +/* Remove entry from the list of allocated objects. */ + +static inline void TRK_free_buf(void* ptr, const char* file, const char* func, + u32 line) { + + u32 i, bucket; + + if (!ptr) return; + + bucket = TRKH(ptr); + + /* Find the element on the list... */ + + for (i = 0; i < TRK_cnt[bucket]; i++) + + if (TRK[bucket][i].ptr == ptr) { + + TRK[bucket][i].ptr = 0; + return; + + } + + WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", + func, file, line); + +} + + +/* Do a final report on all non-deallocated objects. */ + +static inline void TRK_report(void) { + + u32 i, bucket; + + fflush(0); + + for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) + for (i = 0; i < TRK_cnt[bucket]; i++) + if (TRK[bucket][i].ptr) + WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", + TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); + +} + + +/* Simple wrappers for non-debugging functions: */ + +static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, + u32 line) { + + void* ret = DFL_ck_alloc(size); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_realloc(orig, size); + TRK_free_buf(orig, file, func, line); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_realloc_block(orig, size); + TRK_free_buf(orig, file, func, line); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, + u32 line) { + + void* ret = DFL_ck_strdup(str); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_memdup(mem, size); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_memdup_str(mem, size); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void TRK_ck_free(void* ptr, const char* file, + const char* func, u32 line) { + + TRK_free_buf(ptr, file, func, line); + DFL_ck_free(ptr); + +} + +/* Aliasing user-facing names to tracking functions: */ + +#define ck_alloc(_p1) \ + TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) + +#define ck_alloc_nozero(_p1) \ + TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) + +#define ck_realloc(_p1, _p2) \ + TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_realloc_block(_p1, _p2) \ + TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_strdup(_p1) \ + TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) + +#define ck_memdup(_p1, _p2) \ + TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_memdup_str(_p1, _p2) \ + TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_free(_p1) \ + TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) + +#endif /* ^!DEBUG_BUILD */ + +#endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/AFL/config.h b/AFL/config.h new file mode 100755 index 0000000..52fc352 --- /dev/null +++ b/AFL/config.h @@ -0,0 +1,357 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - vaguely configurable bits + ---------------------------------------------- + + Written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_CONFIG_H +#define _HAVE_CONFIG_H + +#include "types.h" + +/* Version string: */ + +#define VERSION "2.56b" + +/****************************************************** + * * + * Settings that may be of interest to power users: * + * * + ******************************************************/ + +/* Comment out to disable terminal colors (note that this makes afl-analyze + a lot less nice): */ + +#define USE_COLOR + +/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ + +#define FANCY_BOXES + +/* Default timeout for fuzzed code (milliseconds). This is the upper bound, + also used for detecting hangs; the actual value is auto-scaled: */ + +#define EXEC_TIMEOUT 1000 + +/* Timeout rounding factor when auto-scaling (milliseconds): */ + +#define EXEC_TM_ROUND 20 + +/* Default memory limit for child process (MB): */ + +#ifndef __x86_64__ +# define MEM_LIMIT 25 +#else +# define MEM_LIMIT 50 +#endif /* ^!__x86_64__ */ + +/* Default memory limit when running in QEMU mode (MB): */ + +#define MEM_LIMIT_QEMU 200 + +/* Number of calibration cycles per every new test case (and for test + cases that show variable behavior): */ + +#define CAL_CYCLES 8 +#define CAL_CYCLES_LONG 40 + +/* Number of subsequent timeouts before abandoning an input file: */ + +#define TMOUT_LIMIT 250 + +/* Maximum number of unique hangs or crashes to record: */ + +#define KEEP_UNIQUE_HANG 500 +#define KEEP_UNIQUE_CRASH 5000 + +/* Baseline number of random tweaks during a single 'havoc' stage: */ + +#define HAVOC_CYCLES 256 +#define HAVOC_CYCLES_INIT 1024 + +/* Maximum multiplier for the above (should be a power of two, beware + of 32-bit int overflows): */ + +#define HAVOC_MAX_MULT 16 + +/* Absolute minimum number of havoc cycles (after all adjustments): */ + +#define HAVOC_MIN 16 + +/* Maximum stacking for havoc-stage tweaks. The actual value is calculated + like this: + + n = random between 1 and HAVOC_STACK_POW2 + stacking = 2^n + + In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or + 128 stacked tweaks: */ + +#define HAVOC_STACK_POW2 7 + +/* Caps on block sizes for cloning and deletion operations. Each of these + ranges has a 33% probability of getting picked, except for the first + two cycles where smaller blocks are favored: */ + +#define HAVOC_BLK_SMALL 32 +#define HAVOC_BLK_MEDIUM 128 +#define HAVOC_BLK_LARGE 1500 + +/* Extra-large blocks, selected very rarely (<5% of the time): */ + +#define HAVOC_BLK_XL 32768 + +/* Probabilities of skipping non-favored entries in the queue, expressed as + percentages: */ + +#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ +#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ +#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ + +/* Splicing cycle count: */ + +#define SPLICE_CYCLES 15 + +/* Nominal per-splice havoc cycle length: */ + +#define SPLICE_HAVOC 32 + +/* Maximum offset for integer addition / subtraction stages: */ + +#define ARITH_MAX 35 + +/* Limits for the test case trimmer. The absolute minimum chunk size; and + the starting and ending divisors for chopping up the input file: */ + +#define TRIM_MIN_BYTES 4 +#define TRIM_START_STEPS 16 +#define TRIM_END_STEPS 1024 + +/* Maximum size of input file, in bytes (keep under 100MB): */ + +#define MAX_FILE (1 * 1024 * 1024) + +/* The same, for the test case minimizer: */ + +#define TMIN_MAX_FILE (10 * 1024 * 1024) + +/* Block normalization steps for afl-tmin: */ + +#define TMIN_SET_MIN_SIZE 4 +#define TMIN_SET_STEPS 128 + +/* Maximum dictionary token size (-x), in bytes: */ + +#define MAX_DICT_FILE 128 + +/* Length limits for auto-detected dictionary tokens: */ + +#define MIN_AUTO_EXTRA 3 +#define MAX_AUTO_EXTRA 32 + +/* Maximum number of user-specified dictionary tokens to use in deterministic + steps; past this point, the "extras/user" step will be still carried out, + but with proportionally lower odds: */ + +#define MAX_DET_EXTRAS 200 + +/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing + (first value), and to keep in memory as candidates. The latter should be much + higher than the former. */ + +#define USE_AUTO_EXTRAS 50 +#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) + +/* Scaling factor for the effector map used to skip some of the more + expensive deterministic steps. The actual divisor is set to + 2^EFF_MAP_SCALE2 bytes: */ + +#define EFF_MAP_SCALE2 3 + +/* Minimum input file length at which the effector logic kicks in: */ + +#define EFF_MIN_LEN 128 + +/* Maximum effector density past which everything is just fuzzed + unconditionally (%): */ + +#define EFF_MAX_PERC 90 + +/* UI refresh frequency (Hz): */ + +#define UI_TARGET_HZ 5 + +/* Fuzzer stats file and plot update intervals (sec): */ + +#define STATS_UPDATE_SEC 60 +#define PLOT_UPDATE_SEC 5 + +/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ + +#define AVG_SMOOTHING 16 + +/* Sync interval (every n havoc cycles): */ + +#define SYNC_INTERVAL 5 + +/* Output directory reuse grace period (minutes): */ + +#define OUTPUT_GRACE 25 + +/* Uncomment to use simple file names (id_NNNNNN): */ + +// #define SIMPLE_FILES + +/* List of interesting values to use in fuzzing. */ + +#define INTERESTING_8 \ + -128, /* Overflow signed 8-bit when decremented */ \ + -1, /* */ \ + 0, /* */ \ + 1, /* */ \ + 16, /* One-off with common buffer size */ \ + 32, /* One-off with common buffer size */ \ + 64, /* One-off with common buffer size */ \ + 100, /* One-off with common buffer size */ \ + 127 /* Overflow signed 8-bit when incremented */ + +#define INTERESTING_16 \ + -32768, /* Overflow signed 16-bit when decremented */ \ + -129, /* Overflow signed 8-bit */ \ + 128, /* Overflow signed 8-bit */ \ + 255, /* Overflow unsig 8-bit when incremented */ \ + 256, /* Overflow unsig 8-bit */ \ + 512, /* One-off with common buffer size */ \ + 1000, /* One-off with common buffer size */ \ + 1024, /* One-off with common buffer size */ \ + 4096, /* One-off with common buffer size */ \ + 32767 /* Overflow signed 16-bit when incremented */ + +#define INTERESTING_32 \ + -2147483648LL, /* Overflow signed 32-bit when decremented */ \ + -100663046, /* Large negative number (endian-agnostic) */ \ + -32769, /* Overflow signed 16-bit */ \ + 32768, /* Overflow signed 16-bit */ \ + 65535, /* Overflow unsig 16-bit when incremented */ \ + 65536, /* Overflow unsig 16 bit */ \ + 100663045, /* Large positive number (endian-agnostic) */ \ + 2147483647 /* Overflow signed 32-bit when incremented */ + +/*********************************************************** + * * + * Really exotic stuff you probably don't want to touch: * + * * + ***********************************************************/ + +/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ + +#define RESEED_RNG 10000 + +/* Maximum line length passed from GCC to 'as' and used for parsing + configuration files: */ + +#define MAX_LINE 8192 + +/* Environment variable used to pass SHM ID to the called program. */ + +#define SHM_ENV_VAR "__AFL_SHM_ID" + +/* Other less interesting, internal-only variables. */ + +#define CLANG_ENV_VAR "__AFL_CLANG_MODE" +#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" +#define PERSIST_ENV_VAR "__AFL_PERSISTENT" +#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" + +/* In-code signatures for deferred and persistent mode. */ + +#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" +#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" + +/* Distinctive bitmap signature used to indicate failed execution: */ + +#define EXEC_FAIL_SIG 0xfee1dead + +/* Distinctive exit code used to indicate MSAN trip condition: */ + +#define MSAN_ERROR 86 + +/* Designated file descriptors for forkserver commands (the application will + use FORKSRV_FD and FORKSRV_FD + 1): */ + +#define FORKSRV_FD 198 + +/* Fork server init timeout multiplier: we'll wait the user-selected + timeout plus this much for the fork server to spin up. */ + +#define FORK_WAIT_MULT 10 + +/* Calibration timeout adjustments, to be a bit more generous when resuming + fuzzing sessions or trying to calibrate already-added internal finds. + The first value is a percentage, the other is in milliseconds: */ + +#define CAL_TMOUT_PERC 125 +#define CAL_TMOUT_ADD 50 + +/* Number of chances to calibrate a case before giving up: */ + +#define CAL_CHANCES 3 + +/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than + 2; you probably want to keep it under 18 or so for performance reasons + (adjusting AFL_INST_RATIO when compiling is probably a better way to solve + problems with complex programs). You need to recompile the target binary + after changing this - otherwise, SEGVs may ensue. */ + +#define MAP_SIZE_POW2 18 +#define MAP_SIZE (1 << MAP_SIZE_POW2) + +/* Maximum allocator request size (keep well under INT_MAX): */ + +#define MAX_ALLOC 0x40000000 + +/* A made-up hashing seed: */ + +#define HASH_CONST 0xa5b35705 + +/* Constants for afl-gotcpu to control busy loop timing: */ + +#define CTEST_TARGET_MS 5000 +#define CTEST_CORE_TRG_MS 1000 +#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) + +/* Uncomment this to use inferior block-coverage-based instrumentation. Note + that you need to recompile the target binary for this to have any effect: */ + +// #define COVERAGE_ONLY + +/* Uncomment this to ignore hit counts and output just one bit per tuple. + As with the previous setting, you will need to recompile the target + binary: */ + +// #define SKIP_COUNTS + +/* Uncomment this to use instrumentation data to record newly discovered paths, + but do not use them as seeds for fuzzing. This is useful for conveniently + measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ + +// #define IGNORE_FINDS + +#endif /* ! _HAVE_CONFIG_H */ diff --git a/AFL/debug.h b/AFL/debug.h new file mode 100755 index 0000000..5f75974 --- /dev/null +++ b/AFL/debug.h @@ -0,0 +1,258 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - debug / error handling macros + -------------------------------------------------- + + Written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_DEBUG_H +#define _HAVE_DEBUG_H + +#include + +#include "types.h" +#include "config.h" + +/******************* + * Terminal colors * + *******************/ + +#ifdef USE_COLOR + +# define cBLK "\x1b[0;30m" +# define cRED "\x1b[0;31m" +# define cGRN "\x1b[0;32m" +# define cBRN "\x1b[0;33m" +# define cBLU "\x1b[0;34m" +# define cMGN "\x1b[0;35m" +# define cCYA "\x1b[0;36m" +# define cLGR "\x1b[0;37m" +# define cGRA "\x1b[1;90m" +# define cLRD "\x1b[1;91m" +# define cLGN "\x1b[1;92m" +# define cYEL "\x1b[1;93m" +# define cLBL "\x1b[1;94m" +# define cPIN "\x1b[1;95m" +# define cLCY "\x1b[1;96m" +# define cBRI "\x1b[1;97m" +# define cRST "\x1b[0m" + +# define bgBLK "\x1b[40m" +# define bgRED "\x1b[41m" +# define bgGRN "\x1b[42m" +# define bgBRN "\x1b[43m" +# define bgBLU "\x1b[44m" +# define bgMGN "\x1b[45m" +# define bgCYA "\x1b[46m" +# define bgLGR "\x1b[47m" +# define bgGRA "\x1b[100m" +# define bgLRD "\x1b[101m" +# define bgLGN "\x1b[102m" +# define bgYEL "\x1b[103m" +# define bgLBL "\x1b[104m" +# define bgPIN "\x1b[105m" +# define bgLCY "\x1b[106m" +# define bgBRI "\x1b[107m" + +#else + +# define cBLK "" +# define cRED "" +# define cGRN "" +# define cBRN "" +# define cBLU "" +# define cMGN "" +# define cCYA "" +# define cLGR "" +# define cGRA "" +# define cLRD "" +# define cLGN "" +# define cYEL "" +# define cLBL "" +# define cPIN "" +# define cLCY "" +# define cBRI "" +# define cRST "" + +# define bgBLK "" +# define bgRED "" +# define bgGRN "" +# define bgBRN "" +# define bgBLU "" +# define bgMGN "" +# define bgCYA "" +# define bgLGR "" +# define bgGRA "" +# define bgLRD "" +# define bgLGN "" +# define bgYEL "" +# define bgLBL "" +# define bgPIN "" +# define bgLCY "" +# define bgBRI "" + +#endif /* ^USE_COLOR */ + +/************************* + * Box drawing sequences * + *************************/ + +#ifdef FANCY_BOXES + +# define SET_G1 "\x1b)0" /* Set G1 for box drawing */ +# define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ +# define bSTART "\x0e" /* Enter G1 drawing mode */ +# define bSTOP "\x0f" /* Leave G1 drawing mode */ +# define bH "q" /* Horizontal line */ +# define bV "x" /* Vertical line */ +# define bLT "l" /* Left top corner */ +# define bRT "k" /* Right top corner */ +# define bLB "m" /* Left bottom corner */ +# define bRB "j" /* Right bottom corner */ +# define bX "n" /* Cross */ +# define bVR "t" /* Vertical, branch right */ +# define bVL "u" /* Vertical, branch left */ +# define bHT "v" /* Horizontal, branch top */ +# define bHB "w" /* Horizontal, branch bottom */ + +#else + +# define SET_G1 "" +# define RESET_G1 "" +# define bSTART "" +# define bSTOP "" +# define bH "-" +# define bV "|" +# define bLT "+" +# define bRT "+" +# define bLB "+" +# define bRB "+" +# define bX "+" +# define bVR "+" +# define bVL "+" +# define bHT "+" +# define bHB "+" + +#endif /* ^FANCY_BOXES */ + +/*********************** + * Misc terminal codes * + ***********************/ + +#define TERM_HOME "\x1b[H" +#define TERM_CLEAR TERM_HOME "\x1b[2J" +#define cEOL "\x1b[0K" +#define CURSOR_HIDE "\x1b[?25l" +#define CURSOR_SHOW "\x1b[?25h" + +/************************ + * Debug & error macros * + ************************/ + +/* Just print stuff to the appropriate stream. */ + +#ifdef MESSAGES_TO_STDOUT +# define SAYF(x...) printf(x) +#else +# define SAYF(x...) fprintf(stderr, x) +#endif /* ^MESSAGES_TO_STDOUT */ + +/* Show a prefixed warning. */ + +#define WARNF(x...) do { \ + SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Show a prefixed "doing something" message. */ + +#define ACTF(x...) do { \ + SAYF(cLBL "[*] " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Show a prefixed "success" message. */ + +#define OKF(x...) do { \ + SAYF(cLGN "[+] " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Show a prefixed fatal error message (not used in afl). */ + +#define BADF(x...) do { \ + SAYF(cLRD "\n[-] " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Die with a verbose non-OS fatal error message. */ + +#define FATAL(x...) do { \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ + cBRI x); \ + SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + exit(1); \ + } while (0) + +/* Die by calling abort() to provide a core dump. */ + +#define ABORT(x...) do { \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ + cBRI x); \ + SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + abort(); \ + } while (0) + +/* Die while also including the output of perror(). */ + +#define PFATAL(x...) do { \ + fflush(stdout); \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \ + cBRI x); \ + SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ + exit(1); \ + } while (0) + +/* Die with FAULT() or PFAULT() depending on the value of res (used to + interpret different failure modes for read(), write(), etc). */ + +#define RPFATAL(res, x...) do { \ + if (res < 0) PFATAL(x); else FATAL(x); \ + } while (0) + +/* Error-checking versions of read() and write() that call RPFATAL() as + appropriate. */ + +#define ck_write(fd, buf, len, fn) do { \ + u32 _len = (len); \ + s32 _res = write(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ + } while (0) + +#define ck_read(fd, buf, len, fn) do { \ + u32 _len = (len); \ + s32 _res = read(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ + } while (0) + +#endif /* ! _HAVE_DEBUG_H */ diff --git a/AFL/hash.h b/AFL/hash.h new file mode 100755 index 0000000..e17fc8f --- /dev/null +++ b/AFL/hash.h @@ -0,0 +1,111 @@ +/* + Copyright 2016 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - hashing function + ------------------------------------- + + The hash32() function is a variant of MurmurHash3, a good + non-cryptosafe hashing function developed by Austin Appleby. + + For simplicity, this variant does *NOT* accept buffer lengths + that are not divisible by 8 bytes. The 32-bit version is otherwise + similar to the original; the 64-bit one is a custom hack with + mostly-unproven properties. + + Austin's original code is public domain. + + Other code written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_HASH_H +#define _HAVE_HASH_H + +#include "types.h" + +#ifdef __x86_64__ + +#define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) + +static inline u32 hash32(const void* key, u32 len, u32 seed) { + + const u64* data = (u64*)key; + u64 h1 = seed ^ len; + + len >>= 3; + + while (len--) { + + u64 k1 = *data++; + + k1 *= 0x87c37b91114253d5ULL; + k1 = ROL64(k1, 31); + k1 *= 0x4cf5ad432745937fULL; + + h1 ^= k1; + h1 = ROL64(h1, 27); + h1 = h1 * 5 + 0x52dce729; + + } + + h1 ^= h1 >> 33; + h1 *= 0xff51afd7ed558ccdULL; + h1 ^= h1 >> 33; + h1 *= 0xc4ceb9fe1a85ec53ULL; + h1 ^= h1 >> 33; + + return h1; + +} + +#else + +#define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) + +static inline u32 hash32(const void* key, u32 len, u32 seed) { + + const u32* data = (u32*)key; + u32 h1 = seed ^ len; + + len >>= 2; + + while (len--) { + + u32 k1 = *data++; + + k1 *= 0xcc9e2d51; + k1 = ROL32(k1, 15); + k1 *= 0x1b873593; + + h1 ^= k1; + h1 = ROL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + + } + + h1 ^= h1 >> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >> 16; + + return h1; + +} + +#endif /* ^__x86_64__ */ + +#endif /* !_HAVE_HASH_H */ diff --git a/AFL/types.h b/AFL/types.h new file mode 100755 index 0000000..f4a5716 --- /dev/null +++ b/AFL/types.h @@ -0,0 +1,94 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + + +/* + american fuzzy lop - type definitions and minor macros + ------------------------------------------------------ + + Written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_TYPES_H +#define _HAVE_TYPES_H + +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +/* + + Ugh. There is an unintended compiler / glibc #include glitch caused by + combining the u64 type an %llu in format strings, necessitating a workaround. + + In essence, the compiler is always looking for 'unsigned long long' for %llu. + On 32-bit systems, the u64 type (aliased to uint64_t) is expanded to + 'unsigned long long' in , so everything checks out. + + But on 64-bit systems, it is #ifdef'ed in the same file as 'unsigned long'. + Now, it only happens in circumstances where the type happens to have the + expected bit width, *but* the compiler does not know that... and complains + about 'unsigned long' being unsafe to pass to %llu. + + */ + +#ifdef __x86_64__ +typedef unsigned long long u64; +#else +typedef uint64_t u64; +#endif /* ^__x86_64__ */ + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +#ifndef MIN +# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) +# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) +#endif /* !MIN */ + +#define SWAP16(_x) ({ \ + u16 _ret = (_x); \ + (u16)((_ret << 8) | (_ret >> 8)); \ + }) + +#define SWAP32(_x) ({ \ + u32 _ret = (_x); \ + (u32)((_ret << 24) | (_ret >> 24) | \ + ((_ret << 8) & 0x00FF0000) | \ + ((_ret >> 8) & 0x0000FF00)); \ + }) + +#ifdef AFL_LLVM_PASS +# define AFL_R(x) (random() % (x)) +#else +# define R(x) (random() % (x)) +#endif /* ^AFL_LLVM_PASS */ + +#define STRINGIFY_INTERNAL(x) #x +#define STRINGIFY(x) STRINGIFY_INTERNAL(x) + +#define MEM_BARRIER() \ + __asm__ volatile("" ::: "memory") + +#define likely(_x) __builtin_expect(!!(_x), 1) +#define unlikely(_x) __builtin_expect(!!(_x), 0) + +#endif /* ! _HAVE_TYPES_H */ -- Gitee From b6ac710f6992464da9de1dafcea47e03e43795f5 Mon Sep 17 00:00:00 2001 From: Wen Xin Date: Thu, 16 Nov 2023 15:46:05 +0800 Subject: [PATCH 2/9] corpus --- corpus/IR_config | 921 ++++++++++++++++++++++++++++++++++++++ corpus/initlib/init_lib | 174 +++++++ corpus/input/alter_stmt | 5 + corpus/input/create_index | 5 + corpus/input/create_table | 5 + corpus/input/create_view | 4 + corpus/input/delete_stmt | 4 + corpus/input/update | 4 + 8 files changed, 1122 insertions(+) create mode 100755 corpus/IR_config create mode 100755 corpus/initlib/init_lib create mode 100755 corpus/input/alter_stmt create mode 100755 corpus/input/create_index create mode 100755 corpus/input/create_table create mode 100755 corpus/input/create_view create mode 100755 corpus/input/delete_stmt create mode 100755 corpus/input/update diff --git a/corpus/IR_config b/corpus/IR_config new file mode 100755 index 0000000..b234045 --- /dev/null +++ b/corpus/IR_config @@ -0,0 +1,921 @@ +1 1 +3 2 3 0 3 +2 2 +3 3 0 2 3 +3 3 0 0 3 +3 11 +3 71 3 0 3 +3 65 3 0 3 +3 61 3 0 3 +3 123 3 0 3 +3 22 3 0 3 +3 23 3 0 3 +3 26 3 0 3 +3 4 3 0 3 +3 27 3 0 3 +3 37 3 0 3 +3 16 3 0 3 +4 2 +3 35 2 9 3 +3 35 2 12 3 +5 1 +3 196 3 34 3 +6 1 +3 158 3 5 3 +7 1 +3 173 3 6 3 +8 1 +3 269 3 7 3 +9 1 +3 13 1 8 3 +10 1 +3 162 3 158 3 +11 1 +3 25 1 10 3 +12 1 +3 13 3 11 3 +13 2 +3 0 3 0 3 +3 14 3 0 3 +14 2 +3 15 3 0 3 +3 15 3 14 3 +15 3 +4 0 3 0 3 +5 0 3 0 3 +6 0 3 0 3 +16 1 +7 269 3 17 3 +17 2 +3 18 3 0 3 +3 18 8 17 3 +18 18 +9 267 3 19 3 +11 82 10 0 3 +12 107 3 0 3 +13 267 3 20 3 +14 267 3 19 3 +15 267 3 0 3 +16 270 3 0 3 +17 0 3 0 3 +18 271 3 0 3 +19 270 3 0 3 +20 270 3 0 3 +22 267 21 206 10 +22 267 23 0 3 +22 267 24 104 3 +25 271 3 104 3 +26 269 3 0 3 +28 271 27 271 3 +29 267 27 267 3 +19 1 +3 85 3 21 3 +20 1 +3 267 3 19 3 +21 3 +3 0 3 0 3 +30 267 3 0 3 +31 0 3 0 3 +22 1 +18 271 32 269 3 +23 1 +33 24 3 25 3 +24 2 +3 0 3 0 3 +34 0 3 0 3 +25 2 +3 269 3 0 3 +3 269 8 25 3 +26 1 +35 24 3 25 3 +27 1 +3 35 36 33 3 +28 1 +3 196 3 34 3 +29 1 +3 158 3 28 3 +30 1 +3 57 3 29 3 +31 1 +3 162 24 30 3 +32 1 +3 60 3 31 3 +33 1 +3 36 3 32 3 +34 2 +3 0 3 0 3 +37 262 3 0 3 +35 2 +3 0 3 0 3 +3 201 3 0 3 +36 2 +3 0 3 0 3 +5 0 3 0 3 +37 3 +39 59 3 41 3 +39 59 3 44 3 +39 59 3 47 3 +38 1 +3 55 3 56 3 +39 1 +3 49 3 38 3 +40 1 +3 269 3 39 3 +41 1 +3 60 38 40 3 +42 1 +3 57 3 38 3 +43 1 +3 269 24 42 3 +44 1 +3 60 38 43 3 +45 1 +3 48 3 56 3 +46 1 +3 269 3 45 3 +47 1 +3 60 38 46 3 +48 2 +3 124 3 0 3 +40 170 10 124 3 +49 2 +41 50 3 0 3 +40 170 42 50 3 +50 2 +3 51 3 0 3 +3 51 8 50 3 +51 1 +40 52 10 0 3 +52 2 +3 0 3 0 3 +3 53 3 0 3 +53 2 +3 54 3 0 3 +3 54 8 53 3 +54 2 +3 206 3 0 3 +43 0 3 0 3 +55 2 +3 0 3 0 3 +44 269 3 169 3 +56 2 +3 0 3 0 3 +45 57 3 0 3 +57 2 +3 58 3 0 3 +3 58 8 57 3 +58 1 +3 257 46 54 3 +59 4 +3 0 3 0 3 +5 0 3 0 3 +47 0 3 0 3 +48 0 3 0 3 +60 2 +3 0 3 0 3 +6 0 3 0 3 +61 1 +50 64 49 63 3 +62 1 +3 269 40 117 10 +63 1 +3 271 32 62 3 +64 2 +3 0 3 0 3 +51 0 3 0 3 +65 1 +50 69 3 68 3 +66 1 +3 169 44 124 3 +67 1 +3 272 3 66 3 +68 1 +3 70 52 67 3 +69 2 +3 0 3 0 3 +53 0 3 0 3 +70 4 +3 0 3 0 3 +54 0 3 0 3 +55 0 3 0 3 +56 0 3 0 3 +71 2 +50 77 57 74 3 +50 77 57 76 3 +72 1 +3 82 10 79 3 +73 1 +3 269 40 72 3 +74 1 +3 78 3 73 3 +75 1 +3 269 3 80 3 +76 1 +3 78 3 75 3 +77 2 +3 0 3 0 3 +58 0 3 0 3 +78 2 +3 0 3 0 3 +59 0 3 0 3 +79 2 +3 0 3 0 3 +3 80 3 0 3 +80 2 +3 81 44 124 3 +44 124 3 0 3 +81 2 +60 0 3 0 3 +6 0 3 0 3 +82 2 +3 83 3 0 3 +3 83 8 82 3 +83 2 +3 84 3 0 3 +3 107 3 0 3 +84 1 +3 267 3 85 3 +85 1 +3 86 3 99 3 +86 3 +3 89 3 0 3 +3 88 3 0 3 +3 87 3 0 3 +87 13 +61 254 3 0 3 +62 254 3 0 3 +63 255 3 0 3 +64 255 3 0 3 +65 0 3 0 3 +66 0 3 0 3 +67 0 3 0 3 +68 0 3 0 3 +69 254 3 0 3 +70 0 3 0 3 +71 0 3 0 3 +72 0 3 0 3 +73 0 3 0 3 +88 2 +74 0 3 0 3 +75 0 3 0 3 +89 3 +3 95 3 96 3 +3 93 3 90 3 +3 92 3 91 3 +90 1 +3 94 3 96 3 +91 1 +3 252 3 96 3 +92 4 +76 0 3 0 3 +77 0 3 0 3 +78 0 3 0 3 +79 0 3 0 3 +93 2 +80 0 3 0 3 +81 0 3 0 3 +94 2 +3 0 3 0 3 +3 253 3 0 3 +95 5 +82 0 3 0 3 +83 0 3 0 3 +84 0 3 0 3 +85 0 3 0 3 +86 0 3 0 3 +96 2 +3 0 3 0 3 +3 97 3 0 3 +97 2 +3 98 3 0 3 +3 98 3 97 3 +98 3 +87 0 3 0 3 +88 0 3 0 3 +89 0 3 0 3 +99 2 +3 0 3 0 3 +3 100 3 0 3 +100 2 +3 101 3 0 3 +3 101 3 100 3 +101 3 +3 103 3 0 3 +3 102 3 0 3 +3 104 3 0 3 +102 1 +90 206 10 0 3 +103 1 +91 0 3 0 3 +104 2 +92 0 3 0 3 +93 0 3 0 3 +105 2 +3 0 3 0 3 +94 270 3 0 3 +106 1 +95 206 10 0 3 +107 4 +49 122 40 117 10 +3 105 3 109 3 +3 105 3 106 3 +3 105 96 111 3 +108 1 +3 122 40 117 10 +109 1 +3 121 3 108 3 +110 1 +3 116 10 112 3 +111 1 +3 122 40 110 3 +112 1 +97 269 40 113 3 +113 1 +3 170 10 114 3 +114 5 +3 0 3 0 3 +98 115 3 0 3 +99 115 3 0 3 +98 115 99 115 3 +99 115 98 115 3 +115 4 +100 0 3 0 3 +101 0 3 0 3 +102 0 3 0 3 +103 0 3 0 3 +116 2 +3 119 3 0 3 +3 119 8 116 3 +117 2 +3 118 3 0 3 +3 118 8 117 3 +118 2 +3 119 3 0 3 +40 206 10 148 3 +119 2 +3 267 3 148 3 +3 267 40 120 3 +120 1 +3 262 10 148 3 +121 2 +104 0 3 0 3 +51 0 3 0 3 +122 2 +3 0 3 0 3 +3 271 3 0 3 +123 1 +3 124 3 0 3 +124 2 +3 127 3 125 3 +3 201 3 126 3 +125 1 +3 196 3 198 3 +126 1 +3 127 3 125 3 +127 5 +3 129 3 0 3 +3 194 3 0 3 +3 127 105 128 3 +3 127 106 128 3 +3 127 107 128 3 +128 1 +3 195 3 127 3 +129 1 +3 130 3 0 3 +130 1 +108 191 3 135 3 +131 1 +3 155 3 136 3 +132 1 +3 156 3 131 3 +133 1 +3 158 3 132 3 +134 1 +3 160 3 133 3 +135 1 +3 188 3 134 3 +136 2 +3 0 3 0 3 +109 137 3 0 3 +137 2 +3 138 3 0 3 +3 138 8 137 3 +138 1 +3 268 44 139 3 +139 1 +40 140 10 0 3 +140 1 +3 143 3 142 3 +141 1 +3 145 3 149 3 +142 1 +3 144 3 141 3 +143 2 +3 0 3 0 3 +3 268 3 0 3 +144 2 +3 0 3 0 3 +110 205 3 0 3 +145 2 +3 0 3 0 3 +111 146 3 0 3 +146 2 +3 147 3 0 3 +3 147 8 146 3 +147 1 +3 206 3 148 3 +148 3 +3 0 3 0 3 +112 0 3 0 3 +113 0 3 0 3 +149 2 +3 0 3 0 3 +3 150 3 151 3 +150 2 +114 0 3 0 3 +115 0 3 0 3 +151 2 +3 152 3 0 3 +3 153 3 0 3 +152 3 +116 0 3 0 3 +3 262 117 0 3 +118 0 3 0 3 +153 1 +120 152 119 154 3 +154 3 +3 152 3 0 3 +121 0 3 0 3 +3 262 122 0 3 +155 2 +3 0 3 0 3 +123 206 3 0 3 +156 2 +3 0 3 0 3 +124 205 3 157 3 +157 2 +3 0 3 0 3 +125 0 3 0 3 +158 2 +3 0 3 0 3 +3 159 3 0 3 +159 1 +126 206 3 0 3 +160 2 +3 0 3 0 3 +3 161 3 0 3 +161 1 +1 162 3 0 3 +162 2 +3 163 3 0 3 +3 163 8 162 3 +163 2 +3 164 3 0 3 +3 174 3 0 3 +164 4 +3 172 3 0 3 +3 167 3 0 3 +3 166 3 0 3 +3 165 3 0 3 +165 1 +40 163 8 162 10 +166 1 +40 174 10 0 3 +167 2 +3 171 44 168 3 +127 171 44 168 3 +168 1 +3 266 3 169 3 +169 2 +3 0 3 0 3 +40 170 10 0 3 +170 2 +3 267 3 0 3 +3 267 8 170 3 +171 1 +3 194 3 0 3 +172 1 +3 269 3 173 3 +173 2 +3 0 3 0 3 +44 266 3 0 3 +174 6 +3 163 3 176 3 +3 163 3 178 3 +3 163 3 179 3 +3 163 3 180 3 +3 163 3 181 3 +3 163 3 182 3 +175 1 +3 163 32 206 3 +176 1 +3 183 3 175 3 +177 1 +3 163 128 170 10 +178 1 +3 183 3 177 3 +179 1 +3 187 3 175 3 +180 1 +3 187 3 177 3 +181 1 +3 183 3 163 3 +182 1 +3 184 3 164 3 +183 4 +129 0 3 0 3 +130 0 3 0 3 +131 0 3 0 3 +132 0 3 0 3 +184 3 +133 185 129 0 3 +134 186 129 0 3 +135 186 129 0 3 +185 2 +3 0 3 0 3 +136 0 3 0 3 +186 2 +3 0 3 0 3 +137 0 3 0 3 +187 2 +138 186 129 0 3 +139 186 129 0 3 +188 2 +3 189 3 0 3 +3 189 8 188 3 +189 2 +3 190 3 0 3 +3 206 3 173 3 +190 2 +140 0 3 0 3 +3 269 141 0 3 +191 2 +3 0 3 0 3 +3 192 3 0 3 +192 2 +3 193 3 0 3 +3 193 3 192 3 +193 9 +142 0 3 0 3 +132 0 3 0 3 +48 0 3 0 3 +143 0 3 0 3 +144 0 3 0 3 +145 0 3 0 3 +146 0 3 0 3 +147 0 3 0 3 +148 0 3 0 3 +194 2 +40 194 10 0 3 +40 124 10 0 3 +195 3 +3 0 3 0 3 +143 0 3 0 3 +148 0 3 0 3 +196 2 +3 0 3 0 3 +3 197 3 0 3 +197 1 +111 146 3 0 3 +198 2 +3 0 3 0 3 +3 199 3 0 3 +199 1 +37 200 3 0 3 +200 2 +3 262 3 0 3 +3 262 8 262 3 +201 2 +149 202 3 0 3 +150 202 3 0 3 +202 2 +3 203 3 0 3 +3 203 8 202 3 +203 1 +3 269 3 204 3 +204 1 +3 169 44 171 3 +205 2 +3 206 3 0 3 +3 206 8 205 3 +206 1 +3 207 3 0 3 +207 11 +3 207 151 207 3 +3 207 152 207 3 +3 207 119 207 3 +153 207 3 0 3 +3 208 154 0 3 +3 208 155 0 3 +3 208 156 0 3 +3 208 157 0 3 +3 208 158 0 3 +3 208 159 0 3 +3 208 3 0 3 +208 5 +3 208 160 0 3 +3 208 161 0 3 +3 208 3 209 3 +3 208 3 210 3 +3 211 3 0 3 +209 1 +3 258 3 211 3 +210 1 +3 258 3 259 3 +211 13 +3 214 3 260 3 +3 214 162 207 10 +3 214 162 212 3 +3 214 163 207 10 +3 214 163 212 3 +3 214 120 213 3 +3 214 164 213 3 +3 214 165 214 3 +3 214 166 215 3 +3 214 167 215 3 +3 214 168 214 3 +3 214 169 214 3 +3 214 3 0 3 +212 1 +3 207 8 261 10 +213 1 +3 214 119 211 3 +214 11 +3 214 170 214 3 +3 214 171 214 3 +3 214 172 214 3 +3 214 173 214 3 +3 214 174 214 3 +3 214 175 214 3 +3 214 140 214 3 +3 214 176 214 3 +3 214 177 214 3 +3 214 178 214 3 +3 215 3 0 3 +215 15 +3 257 3 0 3 +3 256 3 0 3 +3 262 3 0 3 +3 263 3 0 3 +3 264 3 0 3 +174 215 3 0 3 +175 215 3 0 3 +179 215 3 0 3 +3 171 3 0 3 +180 171 3 0 3 +3 250 3 0 3 +3 244 3 0 3 +90 257 10 0 3 +3 216 3 0 3 +40 207 10 0 3 +216 5 +3 242 3 0 3 +3 221 3 0 3 +3 217 3 0 3 +3 232 3 0 3 +3 223 3 0 3 +217 44 +181 207 10 0 3 +182 207 10 0 3 +183 207 10 0 3 +184 207 10 0 3 +185 207 10 0 3 +186 207 10 0 3 +187 207 10 0 3 +188 207 10 0 3 +189 207 10 0 3 +190 207 10 0 3 +191 207 10 0 3 +192 207 10 0 3 +193 207 10 0 3 +194 207 10 0 3 +195 207 10 0 3 +196 207 10 0 3 +197 207 10 0 3 +198 207 10 0 3 +199 207 8 207 10 +200 207 8 207 10 +201 207 8 207 10 +202 207 8 207 10 +203 207 8 207 10 +204 207 8 207 10 +205 207 8 207 10 +206 207 1 207 10 +207 207 1 207 10 +194 207 1 207 10 +208 207 8 218 3 +202 207 8 218 3 +209 207 8 218 3 +210 207 8 218 3 +211 207 8 218 3 +205 207 8 218 3 +212 207 8 218 3 +208 207 8 219 3 +213 207 8 219 3 +208 207 8 220 3 +214 261 10 0 3 +215 261 10 0 3 +216 207 8 261 10 +217 207 8 261 10 +218 207 8 261 10 +219 207 8 261 10 +218 1 +3 207 8 207 10 +219 1 +3 207 8 218 3 +220 1 +3 207 8 219 3 +221 29 +220 0 3 0 3 +221 0 3 0 3 +222 207 10 0 3 +223 207 10 0 3 +224 207 10 0 3 +225 207 10 0 3 +226 207 10 0 3 +227 207 10 0 3 +228 207 10 0 3 +229 207 10 0 3 +230 207 10 0 3 +231 207 10 0 3 +232 207 10 0 3 +233 207 10 0 3 +234 207 10 0 3 +235 207 10 0 3 +236 207 10 0 3 +237 207 10 0 3 +238 207 10 0 3 +239 207 10 0 3 +240 207 10 0 3 +225 207 8 207 10 +241 207 8 207 10 +242 207 8 207 10 +243 207 8 207 10 +244 207 8 207 10 +236 207 8 207 10 +245 207 8 207 10 +246 207 8 222 3 +222 1 +3 207 8 207 10 +223 11 +247 240 3 0 3 +248 240 3 0 3 +249 240 3 0 3 +250 240 3 0 3 +251 240 3 0 3 +252 262 10 240 3 +253 207 3 225 3 +254 207 3 225 3 +255 207 10 224 3 +256 207 10 224 3 +257 207 8 227 3 +224 1 +3 228 3 240 3 +225 1 +3 230 10 224 3 +226 1 +3 229 3 224 3 +227 1 +3 262 10 226 3 +228 3 +3 0 3 0 3 +258 0 3 0 3 +259 0 3 0 3 +229 3 +3 0 3 0 3 +260 0 3 0 3 +261 0 3 0 3 +230 2 +3 0 3 0 3 +3 231 3 0 3 +231 2 +8 262 3 0 3 +8 262 8 207 3 +232 15 +262 238 3 233 3 +263 207 10 239 3 +264 207 10 239 3 +265 207 10 239 3 +266 239 3 0 3 +267 207 10 239 3 +268 261 10 239 3 +269 238 3 233 3 +270 238 3 233 3 +271 238 3 233 3 +272 207 10 239 3 +273 207 10 239 3 +274 207 10 239 3 +275 207 10 239 3 +276 238 3 236 3 +233 1 +3 207 10 239 3 +234 1 +3 237 10 239 3 +235 1 +3 196 3 234 3 +236 1 +3 261 3 235 3 +237 2 +3 0 3 0 3 +277 264 3 0 3 +238 2 +3 0 3 0 3 +143 0 3 0 3 +239 2 +3 0 3 0 3 +3 240 3 0 3 +240 1 +278 241 3 0 3 +241 2 +3 268 3 0 3 +3 139 3 0 3 +242 3 +279 207 8 243 3 +280 207 8 207 10 +281 207 8 207 10 +243 1 +3 207 8 207 10 +244 1 +283 248 3 245 3 +245 1 +3 246 3 249 282 +246 2 +3 247 3 0 3 +3 247 3 246 3 +247 1 +285 207 284 207 3 +248 2 +3 0 3 0 3 +3 207 3 0 3 +249 2 +3 0 3 0 3 +286 207 3 0 3 +250 2 +287 207 44 251 10 +288 207 8 251 10 +251 8 +62 254 3 0 3 +61 254 3 0 3 +289 254 3 0 3 +87 0 3 0 3 +88 0 3 0 3 +77 252 3 0 3 +80 0 3 0 3 +76 254 3 0 3 +252 3 +3 0 3 0 3 +3 255 3 0 3 +3 253 3 0 3 +253 1 +40 262 8 262 10 +254 2 +3 0 3 0 3 +3 255 3 0 3 +255 1 +40 262 10 0 3 +256 3 +290 0 3 0 3 +291 0 3 0 3 +292 0 3 0 3 +257 2 +3 267 3 0 3 +3 269 293 267 3 +258 6 +46 0 3 0 3 +294 0 3 0 3 +295 0 3 0 3 +296 0 3 0 3 +297 0 3 0 3 +298 0 3 0 3 +259 3 +148 171 3 0 3 +299 171 3 0 3 +300 171 3 0 3 +260 2 +301 171 3 0 3 +302 171 3 0 3 +261 2 +3 207 3 0 3 +3 207 8 261 3 +262 1 +3 0 3 0 3 +263 1 +3 0 3 0 3 +264 1 +3 0 3 0 3 +265 1 +3 0 3 0 3 +266 1 +3 265 3 0 3 +267 1 +3 265 3 0 3 +268 1 +3 265 3 0 3 +269 1 +3 265 3 0 3 +270 1 +3 265 3 0 3 +271 1 +3 265 3 0 3 +272 1 +3 265 3 0 3 diff --git a/corpus/initlib/init_lib b/corpus/initlib/init_lib new file mode 100755 index 0000000..0f64f08 --- /dev/null +++ b/corpus/initlib/init_lib @@ -0,0 +1,174 @@ +CREATE TABLE t0 ( c0 INT UNSIGNED NOT NULL) ; +CREATE TABLE t0 ( c0 DOUBLE ( 1 , 1) VISIBLE ) ; +CREATE TABLE t0 ( c0 DECIMAL ( 1 ) DEFAULT ( 1 ) ) ; +CREATE TABLE t0 ( c0 BOOL ) ; +CREATE TABLE t0 ( c0 CHAR ) ; +CREATE TABLE t0 ( c0 INT , INDEX i0 ( c0 ASC ) ) ; +CREATE TABLE t0 ( c0 TEXT , INDEX i0 ( c0 ( 1 ) ) ) ; +CREATE TABLE t0 ( c0 INT , INDEX i0 ( ( c0 + 1 ) ) ) ; +CREATE TABLE t0 ( c0 INT , CONSTRAINT cc0 UNIQUE i0 ( c0 ) ) ; +CREATE TABLE t0 ( c0 INT , CONSTRAINT cc0 CHECK ( c0 = 1 ) ) ; +CREATE TABLE t0 ( c0 INT , c1 INT , UNIQUE ( c1 ) , CONSTRAINT cc0 FOREIGN KEY i0 ( c0 ) REFERENCES t0 ( c1 ) ON UPDATE CASCADE ON DELETE CASCADE ) ; +CREATE TABLE t0 REPLACE AS SELECT 1 ; +CREATE OR REPLACE ALGORITHM = TEMPTABLE VIEW v0 ( c0 , c1 ) AS SELECT 1 , 2 ; +CREATE UNIQUE INDEX i0 ON t0 ( c0 ) ; +DROP INDEX i0 ON t0 ; +DROP TABLE IF EXISTS t0 , t1 ; +DROP VIEW IF EXISTS v0 , v1 ; +DELETE QUICK FROM t0 LIMIT 1 ; +DELETE t0 FROM t0 ; +UPDATE t0 SET c0 = 1 ; +INSERT INTO t0 ( c0 ) VALUES ( 1 ) AS t1 ( c1 ) ON DUPLICATE KEY UPDATE c0 = 1 ; +INSERT INTO t0 SET c0 = 1 ; +INSERT INTO t0 ( c1 ) SELECT 1 ; +ALTER TABLE t0 ADD COLUMN c1 INT AFTER c0 ; +ALTER TABLE t0 ADD COLUMN ( c1 INT , UNIQUE ( c1 ) ) ; +ALTER TABLE t0 ADD UNIQUE ( c0 ) ; +ALTER TABLE t0 CHANGE COLUMN c0 c1 INT ; +ALTER TABLE t0 MODIFY COLUMN c0 INT FIRST; +ALTER TABLE t0 DROP COLUMN c0 ; +ALTER TABLE t0 DROP FOREIGN KEY cc0 ; +ALTER TABLE t0 DROP PRIMARY KEY ; +ALTER TABLE t0 DROP INDEX i0 ; +ALTER TABLE t0 DROP CHECK cc0 ; +ALTER TABLE t0 DROP CONSTRAINT cc0 ; +ALTER TABLE t0 ALTER COLUMN c0 SET DEFAULT ( 1 ) ; +ALTER TABLE t0 ALTER COLUMN c0 DROP DEFAULT ; +ALTER TABLE t0 ALTER COLUMN c0 SET INVISIBLE ; +ALTER TABLE t0 ALTER INDEX i0 INVISIBLE ; +ALTER TABLE t0 RENAME TO t1 ; +ALTER TABLE t0 RENAME INDEX i0 TO i1 ; +ALTER TABLE t0 RENAME COLUMN c0 TO c1 ; +SELECT c0 FROM t0 ORDER BY c0 LIMIT 1 ; +( SELECT c0 FROM t0 ) ORDER BY c0 LIMIT 1 ; +SELECT c0 FROM t0 UNION SELECT c0 FROM t0 ; +SELECT SQL_NO_CACHE c0 AS c1 FROM ( SELECT c0 FROM t0 ) AS t1 ( c2 ) WHERE c1 = 0 GROUP BY c1 HAVING c1 = 0 ; +SELECT c0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) ; +SELECT t0 . c0 FROM ( t0 CROSS JOIN t0 AS t1 ) ; +SELECT t0 . c0 FROM ( t0 , t0 AS t1 ) ; +SELECT t0 . c0 FROM t0 INNER JOIN t0 AS t1 ON t0 . c0 = t1 . c0 ; +SELECT t0 . c0 FROM t0 INNER JOIN t0 AS t1 USING ( c0 ) ; +SELECT t0 . c0 FROM t0 INNER JOIN t0 AS t1 ; +SELECT t0 . c0 FROM t0 LEFT OUTER JOIN t0 AS t1 ON t0 . c0 = t0 . c1 ; +SELECT t0 . c0 FROM t0 NATURAL INNER JOIN t0 AS t1 ; +WITH t1 ( c1 ) AS ( SELECT 1 ) SELECT c1 FROM t1 ; +WITH RECURSIVE t1 ( c1 ) AS ( SELECT 1 UNION SELECT c1 + 1 FROM t1 WHERE c1 < 10 ) SELECT c1 FROM t1 ; +SELECT * FROM t0 ; +SELECT c0 = ( SELECT c0 FROM t0 LIMIT 1 ) FROM t0 ; +SELECT c0 = ALL ( SELECT c0 FROM t0 ) FROM t0 ; +SELECT c0 IN ( SELECT c0 FROM t0 ) FROM t0 ; +SELECT TRUE ; +SELECT 1 ; +SELECT 1.1 ; +SELECT 'string' ; +SELECT CAST ( c0 AS UNSIGNED ) FROM t0 ; +SELECT CONVERT ( c0 , UNSIGNED ) FROM t0 ; +SELECT CASE c0 WHEN 1 THEN 1 ELSE 2 END FROM t0 ; +SELECT DEFAULT ( c0 ) FROM t0 ; +SELECT IF ( c0 , c0 , 1 ) FROM t0 ; +SELECT IFNULL ( c0 , 1 ) FROM t0 ; +SELECT NULLIF ( c0 , 1 ) FROM t0 ; +SELECT PI ( ) ; +SELECT RAND ( ) ; +SELECT ABS ( c0 ) FROM t0 ; +SELECT ACOS ( c0 ) FROM t0 ; +SELECT ASIN ( c0 ) FROM t0 ; +SELECT ATAN ( c0 ) FROM t0 ; +SELECT CEILING ( c0 ) FROM t0 ; +SELECT COS ( c0 ) FROM t0 ; +SELECT COT ( c0 ) FROM t0 ; +SELECT DEGREES ( c0 ) FROM t0 ; +SELECT EXP ( c0 ) FROM t0 ; +SELECT FLOOR ( c0 ) FROM t0 ; +SELECT HEX ( c0 ) FROM t0 ; +SELECT LN ( c0 ) FROM t0 ; +SELECT RADIANS ( c0 ) FROM t0 ; +SELECT RAND ( c0 ) FROM t0 ; +SELECT ROUND ( c0 ) FROM t0 ; +SELECT SIGN ( c0 ) FROM t0 ; +SELECT SIN ( c0 ) FROM t0 ; +SELECT SQRT ( c0 ) FROM t0 ; +SELECT TAN ( c0 ) FROM t0 ; +SELECT ATAN ( 1 , 1 ); +SELECT FORMAT ( 1 , 1 ); +SELECT LOG ( 1 , 1 ); +SELECT MOD ( 1 , 1 ); +SELECT POW ( 1 , 1 ); +SELECT ROUND ( 1 , 1 ); +SELECT TRUNCATE ( 1 , 1 ); +SELECT CONV ( 1 , 1 , 1 ) ; +SELECT ASCII ( c0 ) FROM t0 ; +SELECT BIN ( c0 ) FROM t0 ; +SELECT BIT_LENGTH ( c0 ) FROM t0 ; +SELECT CHAR_LENGTH ( c0 ) FROM t0 ; +SELECT LENGTH ( c0 ) FROM t0 ; +SELECT LOWER ( c0 ) FROM t0 ; +SELECT LTRIM ( c0 ) FROM t0 ; +SELECT OCT ( c0 ) FROM t0 ; +SELECT ORD ( c0 ) FROM t0 ; +SELECT QUOTE ( c0 ) FROM t0 ; +SELECT REVERSE ( c0 ) FROM t0 ; +SELECT RTRIM ( c0 ) FROM t0 ; +SELECT SPACE ( c0 ) FROM t0 ; +SELECT TRIM( c0 ) FROM t0 ; +SELECT TRIM( LEADING FROM c0 ) FROM t0 ; +SELECT TRIM( TRAILING FROM c0 ) FROM t0 ; +SELECT UNHEX ( c0 ) FROM t0 ; +SELECT UPPER ( c0 ) FROM t0 ; +SELECT FIND_IN_SET ( c0 , 'str' ) FROM t0 ; +SELECT INSTR ( c0 , 'str' ) FROM t0 ; +SELECT LEFT ( c0 , 'str' ) FROM t0 ; +SELECT LOCATE ( c0 , 'str' ) FROM t0 ; +SELECT REPEAT ( c0 , 'str' ) FROM t0 ; +SELECT RIGHT ( c0 , 'str' ) FROM t0 ; +SELECT SUBSTRING( c0 , 'str' ) FROM t0 ; +SELECT TRIM( LEADING c0 FROM 'str' ) FROM t0 ; +SELECT TRIM( TRAILING c0 FROM 'str' ) FROM t0 ; +SELECT TRIM( c0 FROM 'str' ) FROM t0 ; +SELECT EXPORT_SET ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT LOCATE ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT LPAD ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT REPLACE ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT RPAD ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT SUBSTRING( c0 , 'str' , 'str' ) FROM t0 ; +SELECT SUBSTRING_INDEX ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT EXPORT_SET ( c0 , 'str' , 'str' , 'str' ) FROM t0 ; +SELECT INSERT ( c0 , 'str' , 'str' , 'str' ) FROM t0 ; +SELECT EXPORT_SET ( c0 , 'str' , 'str' , 'str' , 'str' ) FROM t0 ; +SELECT CHAR ( c0 , 'str' ) FROM t0 ; +SELECT CONCAT ( c0 , 'str' ) FROM t0 ; +SELECT CONCAT_WS ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT ELT ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT FIELD ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT MAKE_SET ( c0 , 'str' , 'str' ) FROM t0 ; +SELECT AVG ( c0 ) FROM t0 ; +SELECT BIT_AND( c0 ) FROM t0 ; +SELECT BIT_OR( c0 ) FROM t0 ; +SELECT BIT_XOR( c0 ) FROM t0 ; +SELECT COUNT( * ) FROM t0 ; +SELECT COUNT( c0 ) FROM t0 ; +SELECT COUNT( DISTINCT c0 , 1 ) FROM t0 ; +SELECT MIN( c0 ) FROM t0 ; +SELECT MAX( c0 ) FROM t0 ; +SELECT SUM( c0 ) FROM t0 ; +SELECT STD( c0 ) FROM t0 ; +SELECT STDDEV_SAMP( c0 ) FROM t0 ; +SELECT VARIANCE( c0 ) FROM t0 ; +SELECT VAR_SAMP( c0 ) FROM t0 ; +SELECT GROUP_CONCAT( c0 , 1 ORDER BY c0 SEPARATOR ',' ) FROM t0 ; +SELECT ROW_NUMBER ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT RANK ( ) OVER ( PARTITION BY c0 ) FROM t0 ; +SELECT DENSE_RANK ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT CUME_DIST ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT PERCENT_RANK ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT NTILE ( 1 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT LEAD ( c0 , 1 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT LAG ( c0 , 1 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT FIRST_VALUE ( c0 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT LAST_VALUE ( c0 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT NTH_VALUE ( c0 , 1 ) FROM FIRST RESPECT NULLS OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; +SELECT 1 IN ( 1 , 2 , 3) ; +SELECT 1 NOT IN ( 1 , 2 , 3) ; +SELECT 1 BETWEEN 1 AND 2 ; +SELECT 1 NOT BETWEEN 1 AND 2 ; +SELECT 1 FROM t0 LEFT OUTER JOIN t1 USING ( c0 ) ; \ No newline at end of file diff --git a/corpus/input/alter_stmt b/corpus/input/alter_stmt new file mode 100755 index 0000000..a5ca0a5 --- /dev/null +++ b/corpus/input/alter_stmt @@ -0,0 +1,5 @@ +CREATE TABLE t0 ( c0 INT , c1 INT ) ; +INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; +ALTER TABLE t0 ADD COLUMN c2 INT AFTER c0 ; +INSERT INTO t0 VALUES ( 1 , 2 , 3 ) , ( 3 , 4 , 5 ) ; +SELECT t0 . c0 FROM ( SELECT c1 FROM t0 ) AS t1 JOIN t0 ON t1 . c1 = t0 . c1 ; \ No newline at end of file diff --git a/corpus/input/create_index b/corpus/input/create_index new file mode 100755 index 0000000..0e9e16c --- /dev/null +++ b/corpus/input/create_index @@ -0,0 +1,5 @@ +CREATE TABLE t0 ( c0 INT , c1 INT ) ; +INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; +CREATE INDEX i0 ON t0 ( c0 ) ; +INSERT INTO t0 VALUES ( 5 , 6 ) , ( 7 , 8 ) ; +SELECT t0 . c0 FROM ( SELECT c1 FROM t0 ) AS t1 JOIN t0 ON t1 . c1 = t0 . c1 ; \ No newline at end of file diff --git a/corpus/input/create_table b/corpus/input/create_table new file mode 100755 index 0000000..b308ab5 --- /dev/null +++ b/corpus/input/create_table @@ -0,0 +1,5 @@ +CREATE TABLE t0 ( c0 INT , c1 INT ) ; +CREATE TABLE t1 ( c0 INT , c1 INT ) ; +INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; +INSERT INTO t0 VALUES ( 5 , 6 ) , ( 7 , 8 ) ; +SELECT t0 . c0 FROM t0 CROSS JOIN t1 ; \ No newline at end of file diff --git a/corpus/input/create_view b/corpus/input/create_view new file mode 100755 index 0000000..90504ac --- /dev/null +++ b/corpus/input/create_view @@ -0,0 +1,4 @@ +CREATE TABLE t0 ( c0 INT , c1 INT ) ; +INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; +CREATE VIEW v0 AS SELECT c0 , c1 , 1 AS c2 FROM t0 ; +WITH t1 AS ( SELECT 1 AS c0 , 2 AS c2 ) SELECT t0 . c0 FROM t0 JOIN t1 ON t0 . c1 = t1 . c2 WHERE t0 . c0 = 0 ; diff --git a/corpus/input/delete_stmt b/corpus/input/delete_stmt new file mode 100755 index 0000000..ae2f664 --- /dev/null +++ b/corpus/input/delete_stmt @@ -0,0 +1,4 @@ +CREATE TABLE t0 ( c0 INT , c1 INT ) ; +INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; +DELETE FROM t0 WHERE c0 = 1 ; +SELECT t0 . c0 FROM t0 AS t1 JOIN t0 ON t1 . c1 = t0 . c1 ; \ No newline at end of file diff --git a/corpus/input/update b/corpus/input/update new file mode 100755 index 0000000..b3d7d35 --- /dev/null +++ b/corpus/input/update @@ -0,0 +1,4 @@ +CREATE TABLE t0 ( c0 INT , c1 INT ) ; +INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; +UPDATE t0 SET c0 = 5 WHERE c0 = 1 ; +WITH t1 AS ( SELECT c0 AS c2 FROM t0 ) SELECT c0 FROM t0 CROSS JOIN t1 WHERE c2 = 2 ; \ No newline at end of file -- Gitee From 074002dce42c76e96debc9dddb654abaa0e4f828 Mon Sep 17 00:00:00 2001 From: Wen Xin Date: Thu, 16 Nov 2023 15:52:28 +0800 Subject: [PATCH 3/9] other --- include/ast.h | 1806 +++++++++++++ include/connector.h | 44 + include/define.h | 797 ++++++ include/instantiate.h | 459 ++++ include/mutate.h | 207 ++ parser/Makefile | 30 + parser/bison.y | 4451 +++++++++++++++++++++++++++++++ parser/flex.l | 339 +++ parser/parser_typedef.h | 51 + src/ast.cpp | 5546 +++++++++++++++++++++++++++++++++++++++ src/connector.cpp | 177 ++ src/instantiate.cpp | 3555 +++++++++++++++++++++++++ src/mutate.cpp | 1359 ++++++++++ src/tool.cpp | 1122 ++++++++ 14 files changed, 19943 insertions(+) create mode 100755 include/ast.h create mode 100755 include/connector.h create mode 100755 include/define.h create mode 100755 include/instantiate.h create mode 100755 include/mutate.h create mode 100755 parser/Makefile create mode 100755 parser/bison.y create mode 100755 parser/flex.l create mode 100755 parser/parser_typedef.h create mode 100755 src/ast.cpp create mode 100755 src/connector.cpp create mode 100755 src/instantiate.cpp create mode 100755 src/mutate.cpp create mode 100755 src/tool.cpp diff --git a/include/ast.h b/include/ast.h new file mode 100755 index 0000000..ea406eb --- /dev/null +++ b/include/ast.h @@ -0,0 +1,1806 @@ +#ifndef __AST_H__ +#define __AST_H__ +#include +#include +#include "define.h" +#include + +using namespace std; + +enum IRTYPE{ +#define DECLARE_TYPE(v) \ + v, +ALLTYPE(DECLARE_TYPE) +#undef DECLARE_TYPE +}; + +enum TERMINAL { +#define DECLARE_TERMINAL(v) \ + v, +ALLTERMINAL(DECLARE_TERMINAL) +#undef DECLARE_TERMINAL +}; + +#define DECLARE_CLASS(v) \ + class v ; +ALLCLASS(DECLARE_CLASS); +#undef DECLARE_CLASS + +enum CASEIDX{ + CASE0, CASE1, CASE2, CASE3, CASE4, CASE5, CASE6, CASE7, CASE8, + CASE9, CASE10, CASE11, CASE12, CASE13, CASE14, CASE15, CASE16, + CASE17, CASE18, CASE19, CASE20, CASE21, CASE22, CASE23, CASE24, + CASE25, CASE26, CASE27, CASE28, CASE29, CASE30, CASE31, CASE32, + CASE33, CASE34, CASE35, CASE36, CASE37, CASE38, CASE39, CASE40, + CASE41, CASE42, CASE43, CASE44, CASE45, CASE46, CASE47, CASE48, + CASE49, CASE50, CASE51, CASE52, CASE53, CASE54, CASE55, CASE56, + CASE57, CASE58, CASE59, CASE60, CASE61, CASE62, CASE63 +}; + +class IROperator{ +public: + IROperator(TERMINAL prefix, TERMINAL middle, TERMINAL suffix): + prefix_(prefix), middle_(middle), suffix_(suffix) {} + + TERMINAL prefix_; + TERMINAL middle_; + TERMINAL suffix_; +}; + +class IR{ +public: + IR(IRTYPE type, IROperator * op, IR * left, IR* right): type_(type), op_(op), left_(left), right_(right) {} + + IR(const IR* ir, IR* left, IR* right){ + this->type_ = ir->type_; + + if(ir->op_ != NULL) + this->op_ = OP3(ir->op_->prefix_, ir->op_->middle_, ir->op_->suffix_); + else + this->op_ = OP3(tEmpty, tEmpty, tEmpty); + + this->left_ = left; + this->right_ = right; + + this->str_val_ = ir->str_val_; + this->long_val_ = ir->long_val_; + } + + union{ + int int_val_; + long long_val_; + double float_val_; + bool bool_val_; + }; + + IRTYPE type_; + + string str_val_; + + IROperator* op_; + IR* left_; + IR* right_; + + string to_string(); + string to_string_core(); + void trim_string(string&); +}; + +class Node{ +public: + Node(){}; + ~Node(){}; + + char length_; + unsigned long int vector_; + + unsigned int case_idx_; + + virtual IR* translate() {}; + virtual void deep_delete() {}; +}; + +IR * deep_copy(const IR * root); +void deep_delete(IR * root); + +class ParseToplevel: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Stmtmulti* stmtmulti_; +}; + +class Stmtmulti: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Stmtmulti* stmtmulti_; + Stmt* stmt_; +}; + +class Stmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + CreateTableStmt* create_table_stmt_; + CreateViewStmt* create_view_stmt_; + CreateIndexStmt* create_index_stmt_; + SelectStmt* select_stmt_; + DropIndexStmt* drop_index_stmt_; + DropTableStmt* drop_table_stmt_; + DropViewStmt* drop_view_stmt_; + DeleteStmt* delete_stmt_; + UpdateStmt* update_stmt_; + InsertStmt* insert_stmt_; + AlterTableStmt* alter_table_stmt_; +}; + +class DeleteStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptSimpleLimit* opt_simple_limit_; + OptOrderClause* opt_order_clause_; + OptWhereClause* opt_where_clause_; + OptAlias* opt_alias_; + TableName* table_name_; + OptDeleteOptions* opt_delete_options_; + OptWithClause* opt_with_clause_; + TableReferenceList* table_reference_list_; + TableList* table_list_; +}; + +class OptDeleteOptions: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + DeleteOptions* delete_options_; +}; + +class DeleteOptions: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + DeleteOption* delete_option_; + DeleteOptions* delete_options_; +}; + +class DeleteOption: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class AlterTableStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + AlterList* alter_list_; + TableName* table_name_; +}; + +class AlterList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + AlterListItem* alter_list_item_; + AlterList* alter_list_; +}; + +class AlterListItem: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptPlace* opt_place_; + FieldDef* field_def_; + ColumnName* column_name_1_; + ColumnName* column_name_2_; + TableElementList* table_element_list_; + TableConstraintDef* table_constraint_def_; + ConstraintName* constraint_name_; + IndexName* index_name_1_; + IndexName* index_name_2_; + ExprRoot* expr_root_; + Visibility* visibility_; + TableName* table_name_; +}; + +class OptPlace: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnName* column_name_; +}; + +class DropIndexStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableName* table_name_; + IndexName* index_name_; +}; + +class DropTableStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableList* table_list_; + IfExists* if_exists_; +}; + +class IfExists: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class TableList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableName* table_name_; + TableList* table_list_; +}; + +class DropViewStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableList* table_list_; + IfExists* if_exists_; +}; + +class UpdateStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptSimpleLimit* opt_simple_limit_; + OptOrderClause* opt_order_clause_; + OptWhereClause* opt_where_clause_; + UpdateList* update_list_; + TableReferenceList* table_reference_list_; + OptIgnore* opt_ignore_; + OptLowPriority* opt_low_priority_; + OptWithClause* opt_with_clause_; +}; + +class OptSimpleLimit: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Iconst* iconst_; +}; + +class OptWithClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WithClause* with_clause_; +}; + +class OptLowPriority: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class InsertStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptInsertUpdateList* opt_insert_update_list_; + OptValuesReference* opt_values_reference_; + InsertFromConstructor* insert_from_constructor_; + TableName* table_name_; + OptIgnore* opt_ignore_; + InsertLockOption* insert_lock_option_; + UpdateList* update_list_; + InsertQueryExpression* insert_query_expression_; +}; + +class InsertQueryExpression: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryExpression* query_expression_; + ColumnList* column_list_; +}; + +class InsertFromConstructor: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ValuesList* values_list_; + ColumnList* column_list_; +}; + +class ValuesList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + RowValue* row_value_; + ValuesList* values_list_; +}; + +class RowValue: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptValues* opt_values_; +}; + +class OptValues: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Values* values_; +}; + +class Values: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprOrDefault* expr_or_default_; + Values* values_; +}; + +class ExprOrDefault: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; +}; + +class OptValuesReference: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptColumnList* opt_column_list_; + TableName* table_name_; +}; + +class OptInsertUpdateList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + UpdateList* update_list_; +}; + +class UpdateList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + UpdateElem* update_elem_; + UpdateList* update_list_; +}; + +class UpdateElem: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprOrDefault* expr_or_default_; + Columnref* columnref_; +}; + +class InsertLockOption: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptIgnore: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class CreateIndexStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + KeyListWithExpression* key_list_with_expression_; + TableName* table_name_; + IndexName* index_name_; + OptUnique* opt_unique_; +}; + +class OptUnique: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class CreateViewStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryExpression* query_expression_; + OptColumnList* opt_column_list_; + ViewName* view_name_; + OptViewAlgorithm* opt_view_algorithm_; + OptOrReplace* opt_or_replace_; +}; + +class OptOrReplace: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptViewAlgorithm: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class CreateTableStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptDuplicateAsQe* opt_duplicate_as_qe_; + TableElementList* table_element_list_; + TableName* table_name_; + OptIfNotExists* opt_if_not_exists_; + OptTemporary* opt_temporary_; + DuplicateAsQe* duplicate_as_qe_; +}; + +class OptTemporary: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptIfNotExists: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptDuplicateAsQe: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + DuplicateAsQe* duplicate_as_qe_; +}; + +class DuplicateAsQe: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryExpression* query_expression_; + Duplicate* duplicate_; +}; + +class Duplicate: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class TableElementList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableElement* table_element_; + TableElementList* table_element_list_; +}; + +class TableElement: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnDef* column_def_; + TableConstraintDef* table_constraint_def_; +}; + +class ColumnDef: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + FieldDef* field_def_; + ColumnName* column_name_; +}; + +class FieldDef: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptColumnAttributeList* opt_column_attribute_list_; + DataType* data_type_; +}; + +class DataType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + NumberType* number_type_; + BoolType* bool_type_; + StringType* string_type_; +}; + +class StringType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptFieldLength* opt_field_length_; + FieldLength* field_length_; +}; + +class BoolType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class NumberType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptFieldOptions* opt_field_options_; + IntType* int_type_; + OptPrecision* opt_precision_; + RealType* real_type_; + FloatOptions* float_options_; + NumericType* numeric_type_; +}; + +class NumericType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class RealType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptPrecision: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Precision* precision_; +}; + +class IntType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptFieldOptions: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + FieldOptionList* field_option_list_; +}; + +class FieldOptionList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + FieldOption* field_option_; + FieldOptionList* field_option_list_; +}; + +class FieldOption: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptColumnAttributeList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnAttributeList* column_attribute_list_; +}; + +class ColumnAttributeList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnAttribute* column_attribute_; + ColumnAttributeList* column_attribute_list_; +}; + +class ColumnAttribute: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + NotNull* not_null_; + DefaultAttribute* default_attribute_; + Visibility* visibility_; +}; + +class DefaultAttribute: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; +}; + +class NotNull: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class Visibility: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptConstraintName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ConstraintName* constraint_name_; +}; + +class CheckConstraint: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; +}; + +class TableConstraintDef: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + KeyListWithExpression* key_list_with_expression_; + OptIndexName* opt_index_name_; + ConstraintKeyType* constraint_key_type_; + OptConstraintName* opt_constraint_name_; + CheckConstraint* check_constraint_; + References* references_; + KeyList* key_list_; +}; + +class References: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptOnUpdateDelete* opt_on_update_delete_; + ColumnList* column_list_; + TableName* table_name_; +}; + +class OptOnUpdateDelete: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OnUpdateOption* on_update_option_1_; + OnUpdateOption* on_update_option_2_; +}; + +class OnUpdateOption: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class KeyList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + KeyPart* key_part_; + KeyList* key_list_; +}; + +class KeyListWithExpression: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + KeyPartWithExpression* key_part_with_expression_; + KeyListWithExpression* key_list_with_expression_; +}; + +class KeyPartWithExpression: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + KeyPart* key_part_; + OptOrderingDirection* opt_ordering_direction_; + ExprRoot* expr_root_; +}; + +class KeyPart: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptOrderingDirection* opt_ordering_direction_; + ColumnName* column_name_; + Iconst* iconst_; +}; + +class ConstraintKeyType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptIndexName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + IndexName* index_name_; +}; + +class SelectStmt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryExpression* query_expression_; +}; + +class QueryExpression: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptLimitClause* opt_limit_clause_; + OptOrderClause* opt_order_clause_; + QueryExpressionBody* query_expression_body_; + WithClause* with_clause_; +}; + +class QueryExpressionBody: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryPrimary* query_primary_; + QueryExpressionParens* query_expression_parens_; + QueryExpressionBody* query_expression_body_1_; + QueryExpressionBody* query_expression_body_2_; + OptUnionOption* opt_union_option_; +}; + +class QueryPrimary: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QuerySpecification* query_specification_; +}; + +class QuerySpecification: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptWindowClause* opt_window_clause_; + OptHavingClause* opt_having_clause_; + OptGroupClause* opt_group_clause_; + OptWhereClause* opt_where_clause_; + OptFromClause* opt_from_clause_; + SelectItemList* select_item_list_; + OptSelectOptions* opt_select_options_; +}; + +class OptWindowClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowDefinitionList* window_definition_list_; +}; + +class WindowDefinitionList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowDefinition* window_definition_; + WindowDefinitionList* window_definition_list_; +}; + +class WindowDefinition: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowSpec* window_spec_; + WindowName* window_name_; +}; + +class WindowSpec: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowSpecDetails* window_spec_details_; +}; + +class WindowSpecDetails: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptWindowFrameClause* opt_window_frame_clause_; + OptWindowOrderByClause* opt_window_order_by_clause_; + OptPartitionClause* opt_partition_clause_; + OptExistingWindowName* opt_existing_window_name_; +}; + +class OptExistingWindowName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowName* window_name_; +}; + +class OptPartitionClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRootList* expr_root_list_; +}; + +class OptWindowOrderByClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OrderList* order_list_; +}; + +class OrderList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OrderExpr* order_expr_; + OrderList* order_list_; +}; + +class OrderExpr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptOrderingDirection* opt_ordering_direction_; + ExprRoot* expr_root_; +}; + +class OptOrderingDirection: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptWindowFrameClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowFrameExtent* window_frame_extent_; + WindowFrameUnits* window_frame_units_; +}; + +class WindowFrameUnits: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class WindowFrameExtent: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowFrameStart* window_frame_start_; + WindowFrameBetween* window_frame_between_; +}; + +class WindowFrameStart: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Iconst* iconst_; +}; + +class WindowFrameBetween: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowFrameBound* window_frame_bound_; + WindowFrameStart* window_frame_start_; +}; + +class WindowFrameBound: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowFrameStart* window_frame_start_; + Iconst* iconst_; +}; + +class OptHavingClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; +}; + +class OptGroupClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OlapOpt* olap_opt_; + ExprRootList* expr_root_list_; +}; + +class OlapOpt: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptWhereClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WhereClause* where_clause_; +}; + +class WhereClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; +}; + +class OptFromClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + FromClause* from_clause_; +}; + +class FromClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableReferenceList* table_reference_list_; +}; + +class TableReferenceList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableReference* table_reference_; + TableReferenceList* table_reference_list_; +}; + +class TableReference: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableFactor* table_factor_; + JoinedTable* joined_table_; +}; + +class TableFactor: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + SingleTable* single_table_; + DerivedTable* derived_table_; + JoinedTableParens* joined_table_parens_; + TableReferenceListParens* table_reference_list_parens_; +}; + +class TableReferenceListParens: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableReferenceList* table_reference_list_; + TableReference* table_reference_; +}; + +class JoinedTableParens: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + JoinedTable* joined_table_; +}; + +class DerivedTable: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptColumnList* opt_column_list_; + Alias* alias_; + Subquery* subquery_; +}; + +class OptColumnList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnList* column_list_; +}; + +class ColumnList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnName* column_name_; + ColumnList* column_list_; +}; + +class Subquery: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryExpressionParens* query_expression_parens_; +}; + +class SingleTable: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptAlias* opt_alias_; + TableName* table_name_; +}; + +class OptAlias: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Alias* alias_; +}; + +class JoinedTable: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; + TableReference* table_reference_1_; + TableReference* table_reference_2_; + InnerJoinType* inner_join_type_; + ColumnList* column_list_; + OuterJoinType* outer_join_type_; + TableFactor* table_factor_; + NaturalJoinType* natural_join_type_; +}; + +class InnerJoinType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class NaturalJoinType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptInner* opt_inner_; + OptOuter* opt_outer_; +}; + +class OptInner: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptOuter: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OuterJoinType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptOuter* opt_outer_; +}; + +class SelectItemList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + SelectItem* select_item_; + SelectItemList* select_item_list_; +}; + +class SelectItem: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableWild* table_wild_; + OptAlias* opt_alias_; + ExprRoot* expr_root_; +}; + +class TableWild: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + TableName* table_name_; +}; + +class OptSelectOptions: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + SelectOptionList* select_option_list_; +}; + +class SelectOptionList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + SelectOption* select_option_; + SelectOptionList* select_option_list_; +}; + +class SelectOption: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class QueryExpressionParens: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + QueryExpressionParens* query_expression_parens_; + QueryExpression* query_expression_; +}; + +class OptUnionOption: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptOrderClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OrderClause* order_clause_; +}; + +class OrderClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OrderList* order_list_; +}; + +class OptLimitClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + LimitClause* limit_clause_; +}; + +class LimitClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + LimitOptions* limit_options_; +}; + +class LimitOptions: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Iconst* iconst_1_; + Iconst* iconst_2_; +}; + +class WithClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WithList* with_list_; +}; + +class WithList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + CommonTableExpr* common_table_expr_; + WithList* with_list_; +}; + +class CommonTableExpr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Subquery* subquery_; + OptColumnList* opt_column_list_; + TableName* table_name_; +}; + +class ExprRootList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ExprRoot* expr_root_; + ExprRootList* expr_root_list_; +}; + +class ExprRoot: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_; +}; + +class Expr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_1_; + Expr* expr_2_; + BoolPri* bool_pri_; +}; + +class BoolPri: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + BoolPri* bool_pri_; + Predicate* predicate_; + CompOp* comp_op_; + AllSubquery* all_subquery_; +}; + +class Predicate: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + InSubquery* in_subquery_; + BitExpr* bit_expr_1_; + BitExpr* bit_expr_2_; + Expr* expr_; + ExprList* expr_list_; + Predicate* predicate_; + SimpleExpr* simple_expr_; +}; + +class BitExpr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + BitExpr* bit_expr_1_; + BitExpr* bit_expr_2_; + SimpleExpr* simple_expr_; +}; + +class SimpleExpr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Columnref* columnref_; + Literal* literal_; + Iconst* iconst_; + Fconst* fconst_; + Sconst* sconst_; + SimpleExpr* simple_expr_; + Subquery* subquery_; + TypeCast* type_cast_; + CaseExpr* case_expr_; + Function* function_; + Expr* expr_; +}; + +class Function: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ControlFunction* control_function_; + MathFunction* math_function_; + StringFunction* string_function_; + AggregateFunction* aggregate_function_; + WindowFunction* window_function_; +}; + +class StringFunction: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_1_; + Expr* expr_2_; + Expr* expr_3_; + Expr* expr_4_; + Expr* expr_5_; + ExprList* expr_list_; +}; + +class MathFunction: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_1_; + Expr* expr_2_; + Expr* expr_3_; +}; + +class WindowFunction: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowingClause* windowing_clause_; + Iconst* iconst_; + OptNullTreatment* opt_null_treatment_; + OptLeadLagInfo* opt_lead_lag_info_; + Expr* expr_; + OptFromFirstLast* opt_from_first_last_; +}; + +class OptNullTreatment: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptFromFirstLast: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptLeadLagInfo: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + LeadLagInfo* lead_lag_info_; +}; + +class LeadLagInfo: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Iconst* iconst_; + Expr* expr_; +}; + +class AggregateFunction: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptWindowingClause* opt_windowing_clause_; + Expr* expr_; + OptDistinct* opt_distinct_; + ExprList* expr_list_; + OptGconcatSeparator* opt_gconcat_separator_; + OptOrderClause* opt_order_clause_; +}; + +class OptGconcatSeparator: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Sconst* sconst_; +}; + +class OptDistinct: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class OptWindowingClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowingClause* windowing_clause_; +}; + +class WindowingClause: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowNameOrSpec* window_name_or_spec_; +}; + +class WindowNameOrSpec: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WindowName* window_name_; + WindowSpec* window_spec_; +}; + +class ControlFunction: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_1_; + Expr* expr_2_; + Expr* expr_3_; +}; + +class CaseExpr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptElse* opt_else_; + WhenClasueList* when_clasue_list_; + OptExpr* opt_expr_; +}; + +class WhenClasueList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + WhenList* when_list_; + WhenClasueList* when_clasue_list_; +}; + +class WhenList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_1_; + Expr* expr_2_; +}; + +class OptExpr: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_; +}; + +class OptElse: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_; +}; + +class TypeCast: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + CastType* cast_type_; + Expr* expr_; +}; + +class CastType: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + OptFieldLength* opt_field_length_; + FloatOptions* float_options_; +}; + +class FloatOptions: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + FieldLength* field_length_; + Precision* precision_; +}; + +class Precision: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Iconst* iconst_1_; + Iconst* iconst_2_; +}; + +class OptFieldLength: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + FieldLength* field_length_; +}; + +class FieldLength: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Iconst* iconst_; +}; + +class Literal: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class Columnref: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + ColumnName* column_name_; + TableName* table_name_; +}; + +class CompOp: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + +}; + +class AllSubquery: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Subquery* subquery_; +}; + +class InSubquery: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Subquery* subquery_; +}; + +class ExprList: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Expr* expr_; + ExprList* expr_list_; +}; + +class Iconst: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + long int long_val_; +}; + +class Fconst: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + double float_val_; +}; + +class Sconst: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + string str_val_; +}; + +class Ident: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + string str_val_; +}; + +class Alias: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +class ColumnName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +class WindowName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +class TableName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +class ConstraintName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +class IndexName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +class ViewName: public Node { +public: + virtual IR* translate(); + virtual void deep_delete(); + + Ident* ident_; +}; + +#endif \ No newline at end of file diff --git a/include/connector.h b/include/connector.h new file mode 100755 index 0000000..7418dc4 --- /dev/null +++ b/include/connector.h @@ -0,0 +1,44 @@ +#ifndef __CONNECTOR_H__ +#define __CONNECTOR_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include "libpq-fe.h" + +using namespace std; + +#define BUF_SIZE 1024 + +enum class SQLSTATUS { + ssNormal, + ssConnectFailed, + ssServerCrash, + ssSyntaxError, + ssSemanticError, + ssNoDatabase +}; + +class Connector { +public: + Connector(const char* host, const char* userName, const char* password, unsigned int port, const char* serverName); + + SQLSTATUS execute(const char* sql); + bool start_db(const char* file, char* const options[]); + bool close_db(); + +private: + string conninfo_; + string serverName_; + + void reset_database(PGconn* conn); + SQLSTATUS reset_db(); + pid_t get_pid_by_name(); +}; + +#endif \ No newline at end of file diff --git a/include/define.h b/include/define.h new file mode 100755 index 0000000..23d0fce --- /dev/null +++ b/include/define.h @@ -0,0 +1,797 @@ +#ifndef __DEFINE_H__ +#define __DEFINE_H__ + +#define SWITCHSTART switch(case_idx_){ +#define SWITCHEND default: assert(0); } + +#define CASESTART(idx) case CASE##idx: { +#define CASEEND break; } + +#define TRANSLATESTART IR *res = nullptr; +#define TRANSLATEEND return res; + +#define SAFETRANSLATE(a) (assert(a != nullptr), a->translate()) +#define SAFEDELETE(a) if(a != nullptr) a->deep_delete() + +#define OP0() new IROperator(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty) +#define OP3(a,b,c) new IROperator(a,b,c) + +#define ALLTYPE(V) \ + V(kNone) \ + V(kParseToplevel) \ + V(kStmtmulti) \ + V(kStmt) \ + V(kDeleteStmt) \ + V(kDeleteStmtTmp1) \ + V(kDeleteStmtTmp2) \ + V(kDeleteStmtTmp3) \ + V(kDeleteStmtTmp4) \ + V(kDeleteStmtTmp5) \ + V(kDeleteStmtTmp6) \ + V(kDeleteStmtTmp7) \ + V(kDeleteStmtTmp8) \ + V(kOptDeleteOptions) \ + V(kDeleteOptions) \ + V(kDeleteOption) \ + V(kAlterTableStmt) \ + V(kAlterList) \ + V(kAlterListItem) \ + V(kAlterListItemTmp1) \ + V(kAlterListItemTmp2) \ + V(kOptPlace) \ + V(kDropIndexStmt) \ + V(kDropTableStmt) \ + V(kIfExists) \ + V(kTableList) \ + V(kDropViewStmt) \ + V(kUpdateStmt) \ + V(kUpdateStmtTmp1) \ + V(kUpdateStmtTmp2) \ + V(kUpdateStmtTmp3) \ + V(kUpdateStmtTmp4) \ + V(kUpdateStmtTmp5) \ + V(kUpdateStmtTmp6) \ + V(kOptSimpleLimit) \ + V(kOptWithClause) \ + V(kOptLowPriority) \ + V(kInsertStmt) \ + V(kInsertStmtTmp1) \ + V(kInsertStmtTmp2) \ + V(kInsertStmtTmp3) \ + V(kInsertStmtTmp4) \ + V(kInsertStmtTmp5) \ + V(kInsertStmtTmp6) \ + V(kInsertStmtTmp7) \ + V(kInsertStmtTmp8) \ + V(kInsertStmtTmp9) \ + V(kInsertStmtTmp10) \ + V(kInsertQueryExpression) \ + V(kInsertFromConstructor) \ + V(kValuesList) \ + V(kRowValue) \ + V(kOptValues) \ + V(kValues) \ + V(kExprOrDefault) \ + V(kOptValuesReference) \ + V(kOptInsertUpdateList) \ + V(kUpdateList) \ + V(kUpdateElem) \ + V(kInsertLockOption) \ + V(kOptIgnore) \ + V(kCreateIndexStmt) \ + V(kCreateIndexStmtTmp1) \ + V(kCreateIndexStmtTmp2) \ + V(kOptUnique) \ + V(kCreateViewStmt) \ + V(kCreateViewStmtTmp1) \ + V(kCreateViewStmtTmp2) \ + V(kCreateViewStmtTmp3) \ + V(kOptOrReplace) \ + V(kOptViewAlgorithm) \ + V(kCreateTableStmt) \ + V(kCreateTableStmtTmp1) \ + V(kCreateTableStmtTmp2) \ + V(kCreateTableStmtTmp3) \ + V(kCreateTableStmtTmp4) \ + V(kCreateTableStmtTmp5) \ + V(kOptTemporary) \ + V(kOptIfNotExists) \ + V(kOptDuplicateAsQe) \ + V(kDuplicateAsQe) \ + V(kDuplicate) \ + V(kTableElementList) \ + V(kTableElement) \ + V(kColumnDef) \ + V(kFieldDef) \ + V(kDataType) \ + V(kStringType) \ + V(kBoolType) \ + V(kNumberType) \ + V(kNumberTypeTmp1) \ + V(kNumberTypeTmp2) \ + V(kNumericType) \ + V(kRealType) \ + V(kOptPrecision) \ + V(kIntType) \ + V(kOptFieldOptions) \ + V(kFieldOptionList) \ + V(kFieldOption) \ + V(kOptColumnAttributeList) \ + V(kColumnAttributeList) \ + V(kColumnAttribute) \ + V(kDefaultAttribute) \ + V(kNotNull) \ + V(kVisibility) \ + V(kOptConstraintName) \ + V(kCheckConstraint) \ + V(kTableConstraintDef) \ + V(kTableConstraintDefTmp1) \ + V(kTableConstraintDefTmp2) \ + V(kTableConstraintDefTmp3) \ + V(kTableConstraintDefTmp4) \ + V(kReferences) \ + V(kReferencesTmp1) \ + V(kOptOnUpdateDelete) \ + V(kOnUpdateOption) \ + V(kKeyList) \ + V(kKeyListWithExpression) \ + V(kKeyPartWithExpression) \ + V(kKeyPart) \ + V(kKeyPartTmp1) \ + V(kConstraintKeyType) \ + V(kOptIndexName) \ + V(kSelectStmt) \ + V(kQueryExpression) \ + V(kQueryExpressionTmp1) \ + V(kQueryExpressionTmp2) \ + V(kQueryExpressionBody) \ + V(kQueryExpressionBodyTmp1) \ + V(kQueryPrimary) \ + V(kQuerySpecification) \ + V(kQuerySpecificationTmp1) \ + V(kQuerySpecificationTmp2) \ + V(kQuerySpecificationTmp3) \ + V(kQuerySpecificationTmp4) \ + V(kQuerySpecificationTmp5) \ + V(kOptWindowClause) \ + V(kWindowDefinitionList) \ + V(kWindowDefinition) \ + V(kWindowSpec) \ + V(kWindowSpecDetails) \ + V(kWindowSpecDetailsTmp1) \ + V(kWindowSpecDetailsTmp2) \ + V(kOptExistingWindowName) \ + V(kOptPartitionClause) \ + V(kOptWindowOrderByClause) \ + V(kOrderList) \ + V(kOrderExpr) \ + V(kOptOrderingDirection) \ + V(kOptWindowFrameClause) \ + V(kWindowFrameUnits) \ + V(kWindowFrameExtent) \ + V(kWindowFrameStart) \ + V(kWindowFrameBetween) \ + V(kWindowFrameBound) \ + V(kOptHavingClause) \ + V(kOptGroupClause) \ + V(kOlapOpt) \ + V(kOptWhereClause) \ + V(kWhereClause) \ + V(kOptFromClause) \ + V(kFromClause) \ + V(kTableReferenceList) \ + V(kTableReference) \ + V(kTableFactor) \ + V(kTableReferenceListParens) \ + V(kJoinedTableParens) \ + V(kDerivedTable) \ + V(kDerivedTableTmp1) \ + V(kOptColumnList) \ + V(kColumnList) \ + V(kSubquery) \ + V(kSingleTable) \ + V(kOptAlias) \ + V(kJoinedTable) \ + V(kJoinedTableTmp1) \ + V(kJoinedTableTmp2) \ + V(kJoinedTableTmp3) \ + V(kJoinedTableTmp4) \ + V(kJoinedTableTmp5) \ + V(kJoinedTableTmp6) \ + V(kJoinedTableTmp7) \ + V(kJoinedTableTmp8) \ + V(kInnerJoinType) \ + V(kNaturalJoinType) \ + V(kOptInner) \ + V(kOptOuter) \ + V(kOuterJoinType) \ + V(kSelectItemList) \ + V(kSelectItem) \ + V(kTableWild) \ + V(kOptSelectOptions) \ + V(kSelectOptionList) \ + V(kSelectOption) \ + V(kQueryExpressionParens) \ + V(kOptUnionOption) \ + V(kOptOrderClause) \ + V(kOrderClause) \ + V(kOptLimitClause) \ + V(kLimitClause) \ + V(kLimitOptions) \ + V(kWithClause) \ + V(kWithList) \ + V(kCommonTableExpr) \ + V(kCommonTableExprTmp1) \ + V(kExprRootList) \ + V(kExprRoot) \ + V(kExpr) \ + V(kBoolPri) \ + V(kBoolPriTmp1) \ + V(kBoolPriTmp2) \ + V(kPredicate) \ + V(kPredicateTmp1) \ + V(kPredicateTmp2) \ + V(kBitExpr) \ + V(kSimpleExpr) \ + V(kFunction) \ + V(kStringFunction) \ + V(kStringFunctionTmp1) \ + V(kStringFunctionTmp2) \ + V(kStringFunctionTmp3) \ + V(kMathFunction) \ + V(kMathFunctionTmp1) \ + V(kWindowFunction) \ + V(kWindowFunctionTmp1) \ + V(kWindowFunctionTmp2) \ + V(kWindowFunctionTmp3) \ + V(kWindowFunctionTmp4) \ + V(kOptNullTreatment) \ + V(kOptFromFirstLast) \ + V(kOptLeadLagInfo) \ + V(kLeadLagInfo) \ + V(kAggregateFunction) \ + V(kAggregateFunctionTmp1) \ + V(kAggregateFunctionTmp2) \ + V(kAggregateFunctionTmp3) \ + V(kAggregateFunctionTmp4) \ + V(kOptGconcatSeparator) \ + V(kOptDistinct) \ + V(kOptWindowingClause) \ + V(kWindowingClause) \ + V(kWindowNameOrSpec) \ + V(kControlFunction) \ + V(kControlFunctionTmp1) \ + V(kCaseExpr) \ + V(kCaseExprTmp1) \ + V(kWhenClasueList) \ + V(kWhenList) \ + V(kOptExpr) \ + V(kOptElse) \ + V(kTypeCast) \ + V(kCastType) \ + V(kFloatOptions) \ + V(kPrecision) \ + V(kOptFieldLength) \ + V(kFieldLength) \ + V(kLiteral) \ + V(kColumnref) \ + V(kCompOp) \ + V(kAllSubquery) \ + V(kInSubquery) \ + V(kExprList) \ + V(kIconst) \ + V(kFconst) \ + V(kSconst) \ + V(kIdent) \ + V(kAlias) \ + V(kColumnName) \ + V(kWindowName) \ + V(kTableName) \ + V(kConstraintName) \ + V(kIndexName) \ + V(kViewName) \ + +#define ALLCLASS(V) \ + V(ParseToplevel) \ + V(Stmtmulti) \ + V(Stmt) \ + V(DeleteStmt) \ + V(OptDeleteOptions) \ + V(DeleteOptions) \ + V(DeleteOption) \ + V(AlterTableStmt) \ + V(AlterList) \ + V(AlterListItem) \ + V(OptPlace) \ + V(DropIndexStmt) \ + V(DropTableStmt) \ + V(IfExists) \ + V(TableList) \ + V(DropViewStmt) \ + V(UpdateStmt) \ + V(OptSimpleLimit) \ + V(OptWithClause) \ + V(OptLowPriority) \ + V(InsertStmt) \ + V(InsertQueryExpression) \ + V(InsertFromConstructor) \ + V(ValuesList) \ + V(RowValue) \ + V(OptValues) \ + V(Values) \ + V(ExprOrDefault) \ + V(OptValuesReference) \ + V(OptInsertUpdateList) \ + V(UpdateList) \ + V(UpdateElem) \ + V(InsertLockOption) \ + V(OptIgnore) \ + V(CreateIndexStmt) \ + V(OptUnique) \ + V(CreateViewStmt) \ + V(OptOrReplace) \ + V(OptViewAlgorithm) \ + V(CreateTableStmt) \ + V(OptTemporary) \ + V(OptIfNotExists) \ + V(OptDuplicateAsQe) \ + V(DuplicateAsQe) \ + V(Duplicate) \ + V(TableElementList) \ + V(TableElement) \ + V(ColumnDef) \ + V(FieldDef) \ + V(DataType) \ + V(StringType) \ + V(BoolType) \ + V(NumberType) \ + V(NumericType) \ + V(RealType) \ + V(OptPrecision) \ + V(IntType) \ + V(OptFieldOptions) \ + V(FieldOptionList) \ + V(FieldOption) \ + V(OptColumnAttributeList) \ + V(ColumnAttributeList) \ + V(ColumnAttribute) \ + V(DefaultAttribute) \ + V(NotNull) \ + V(Visibility) \ + V(OptConstraintName) \ + V(CheckConstraint) \ + V(TableConstraintDef) \ + V(References) \ + V(OptOnUpdateDelete) \ + V(OnUpdateOption) \ + V(KeyList) \ + V(KeyListWithExpression) \ + V(KeyPartWithExpression) \ + V(KeyPart) \ + V(ConstraintKeyType) \ + V(OptIndexName) \ + V(SelectStmt) \ + V(QueryExpression) \ + V(QueryExpressionBody) \ + V(QueryPrimary) \ + V(QuerySpecification) \ + V(OptWindowClause) \ + V(WindowDefinitionList) \ + V(WindowDefinition) \ + V(WindowSpec) \ + V(WindowSpecDetails) \ + V(OptExistingWindowName) \ + V(OptPartitionClause) \ + V(OptWindowOrderByClause) \ + V(OrderList) \ + V(OrderExpr) \ + V(OptOrderingDirection) \ + V(OptWindowFrameClause) \ + V(WindowFrameUnits) \ + V(WindowFrameExtent) \ + V(WindowFrameStart) \ + V(WindowFrameBetween) \ + V(WindowFrameBound) \ + V(OptHavingClause) \ + V(OptGroupClause) \ + V(OlapOpt) \ + V(OptWhereClause) \ + V(WhereClause) \ + V(OptFromClause) \ + V(FromClause) \ + V(TableReferenceList) \ + V(TableReference) \ + V(TableFactor) \ + V(TableReferenceListParens) \ + V(JoinedTableParens) \ + V(DerivedTable) \ + V(OptColumnList) \ + V(ColumnList) \ + V(Subquery) \ + V(SingleTable) \ + V(OptAlias) \ + V(JoinedTable) \ + V(InnerJoinType) \ + V(NaturalJoinType) \ + V(OptInner) \ + V(OptOuter) \ + V(OuterJoinType) \ + V(SelectItemList) \ + V(SelectItem) \ + V(TableWild) \ + V(OptSelectOptions) \ + V(SelectOptionList) \ + V(SelectOption) \ + V(QueryExpressionParens) \ + V(OptUnionOption) \ + V(OptOrderClause) \ + V(OrderClause) \ + V(OptLimitClause) \ + V(LimitClause) \ + V(LimitOptions) \ + V(WithClause) \ + V(WithList) \ + V(CommonTableExpr) \ + V(ExprRootList) \ + V(ExprRoot) \ + V(Expr) \ + V(BoolPri) \ + V(Predicate) \ + V(BitExpr) \ + V(SimpleExpr) \ + V(Function) \ + V(StringFunction) \ + V(MathFunction) \ + V(WindowFunction) \ + V(OptNullTreatment) \ + V(OptFromFirstLast) \ + V(OptLeadLagInfo) \ + V(LeadLagInfo) \ + V(AggregateFunction) \ + V(OptGconcatSeparator) \ + V(OptDistinct) \ + V(OptWindowingClause) \ + V(WindowingClause) \ + V(WindowNameOrSpec) \ + V(ControlFunction) \ + V(CaseExpr) \ + V(WhenClasueList) \ + V(WhenList) \ + V(OptExpr) \ + V(OptElse) \ + V(TypeCast) \ + V(CastType) \ + V(FloatOptions) \ + V(Precision) \ + V(OptFieldLength) \ + V(FieldLength) \ + V(Literal) \ + V(Columnref) \ + V(CompOp) \ + V(AllSubquery) \ + V(InSubquery) \ + V(ExprList) \ + V(Iconst) \ + V(Fconst) \ + V(Sconst) \ + V(Ident) \ + V(Alias) \ + V(ColumnName) \ + V(WindowName) \ + V(TableName) \ + V(ConstraintName) \ + V(IndexName) \ + V(ViewName) \ + +#define ALLTERMINAL(V) \ + V(tOpSemi) \ + V(tFrom) \ + V(tDelete) \ + V(tEmpty) \ + V(tQuick) \ + V(tLowPriority) \ + V(tIgnore) \ + V(tAlterTable) \ + V(tOpComma) \ + V(tAddColumn) \ + V(tOpRp) \ + V(tAddColumnOpLp) \ + V(tAdd) \ + V(tChangeColumn) \ + V(tModifyColumn) \ + V(tDropColumn) \ + V(tDropForeignKey) \ + V(tDropPrimaryKey) \ + V(tDropIndex) \ + V(tDropCheck) \ + V(tDropConstraint) \ + V(tSetDefaultOpLp) \ + V(tAlterColumn) \ + V(tDropDefault) \ + V(tSet) \ + V(tAlterIndex) \ + V(tRenameTo) \ + V(tTo) \ + V(tRenameIndex) \ + V(tRenameColumn) \ + V(tAfter) \ + V(tFirst) \ + V(tOn) \ + V(tDropTable) \ + V(tIfExists) \ + V(tDropView) \ + V(tUpdate) \ + V(tLimit) \ + V(tInto) \ + V(tInsert) \ + V(tOpLp) \ + V(tValues) \ + V(tOpRpValues) \ + V(tDefault) \ + V(tAs) \ + V(tOnDuplicateKeyUpdate) \ + V(tOpEqual) \ + V(tDelayed) \ + V(tHighPriority) \ + V(tIndex) \ + V(tCreate) \ + V(tUnique) \ + V(tView) \ + V(tOrReplace) \ + V(tAlgorithmOpEqualUndefined) \ + V(tAlgorithmOpEqualMerge) \ + V(tAlgorithmOpEqualTemptable) \ + V(tTable) \ + V(tTemporary) \ + V(tIfNotExists) \ + V(tReplace) \ + V(tChar) \ + V(tBinary) \ + V(tVarchar) \ + V(tVarbinary) \ + V(tLongVarbinary) \ + V(tTinyblob) \ + V(tMediumblob) \ + V(tLongblob) \ + V(tBlob) \ + V(tTinytext) \ + V(tMediumtext) \ + V(tLongtext) \ + V(tText) \ + V(tBool) \ + V(tBoolean) \ + V(tFloat) \ + V(tDecimal) \ + V(tNumeric) \ + V(tFixed) \ + V(tReal) \ + V(tDouble) \ + V(tInt) \ + V(tTinyint) \ + V(tSmallint) \ + V(tMediumint) \ + V(tBigint) \ + V(tSigned) \ + V(tUnsigned) \ + V(tZerofill) \ + V(tDefaultOpLp) \ + V(tNotNull) \ + V(tVisible) \ + V(tInvisible) \ + V(tConstraint) \ + V(tCheckOpLp) \ + V(tForeignKey) \ + V(tReferences) \ + V(tOnUpdate) \ + V(tOnDelete) \ + V(tCascade) \ + V(tSetNull) \ + V(tNoAction) \ + V(tSetDefault) \ + V(tPrimaryKey) \ + V(tUnion) \ + V(tExcept) \ + V(tIntersect) \ + V(tSelect) \ + V(tWindow) \ + V(tPartitionBy) \ + V(tOrderBy) \ + V(tAsc) \ + V(tDesc) \ + V(tRows) \ + V(tRange) \ + V(tUnboundedPreceding) \ + V(tPreceding) \ + V(tCurrentRow) \ + V(tAnd) \ + V(tBetween) \ + V(tUnboundedFollowing) \ + V(tFollowing) \ + V(tHaving) \ + V(tGroupBy) \ + V(tWithRollup) \ + V(tWhere) \ + V(tLateral) \ + V(tUsingOpLp) \ + V(tJoin) \ + V(tInnerJoin) \ + V(tCrossJoin) \ + V(tStraightJoin) \ + V(tNatural) \ + V(tNaturalRight) \ + V(tNaturalLeft) \ + V(tInner) \ + V(tOuter) \ + V(tLeft) \ + V(tRight) \ + V(tOpMul) \ + V(tOpDotOpMul) \ + V(tSqlNoCache) \ + V(tDistinct) \ + V(tSqlSmallResult) \ + V(tSqlBigResult) \ + V(tSqlBufferResult) \ + V(tSqlCalcFoundRows) \ + V(tAll) \ + V(tWith) \ + V(tWithRecursive) \ + V(tOr) \ + V(tXor) \ + V(tNot) \ + V(tIsTrue) \ + V(tIsNotTrue) \ + V(tIsFalse) \ + V(tIsNotFalse) \ + V(tIsUnknown) \ + V(tIsNotUnknown) \ + V(tIsNull) \ + V(tIsNotNull) \ + V(tInOpLp) \ + V(tNotInOpLp) \ + V(tNotBetween) \ + V(tSoundsLike) \ + V(tLike) \ + V(tNotLike) \ + V(tRegexp) \ + V(tNotRegexp) \ + V(tOpOr) \ + V(tOpAnd) \ + V(tOpShl) \ + V(tOpShr) \ + V(tOpAdd) \ + V(tOpSub) \ + V(tOpDivide) \ + V(tOpMod) \ + V(tOpXor) \ + V(tOpNot) \ + V(tExists) \ + V(tAsciiOpLp) \ + V(tBinOpLp) \ + V(tBitLengthOpLp) \ + V(tCharLengthOpLp) \ + V(tLengthOpLp) \ + V(tLowerOpLp) \ + V(tLtrimOpLp) \ + V(tOctOpLp) \ + V(tOrdOpLp) \ + V(tQuoteOpLp) \ + V(tReverseOpLp) \ + V(tRtrimOpLp) \ + V(tSpaceOpLp) \ + V(tTrimOpLp) \ + V(tTrimOpLpLeadingFrom) \ + V(tTrimOpLpTrailingFrom) \ + V(tUnhexOpLp) \ + V(tUpperOpLp) \ + V(tFindInSetOpLp) \ + V(tInstrOpLp) \ + V(tLeftOpLp) \ + V(tLocateOpLp) \ + V(tRepeatOpLp) \ + V(tRightOpLp) \ + V(tSubstringOpLp) \ + V(tTrimOpLpLeading) \ + V(tTrimOpLpTrailing) \ + V(tExportSetOpLp) \ + V(tLpadOpLp) \ + V(tReplaceOpLp) \ + V(tRpadOpLp) \ + V(tSubstringIndexOpLp) \ + V(tInsertOpLp) \ + V(tCharOpLp) \ + V(tConcatOpLp) \ + V(tConcatWsOpLp) \ + V(tEltOpLp) \ + V(tFieldOpLp) \ + V(tMakeSetOpLp) \ + V(tPiOpLpOpRp) \ + V(tRandOpLpOpRp) \ + V(tAbsOpLp) \ + V(tAcosOpLp) \ + V(tAsinOpLp) \ + V(tAtanOpLp) \ + V(tCeilingOpLp) \ + V(tCosOpLp) \ + V(tCotOpLp) \ + V(tDegreesOpLp) \ + V(tExpOpLp) \ + V(tFloorOpLp) \ + V(tHexOpLp) \ + V(tLnOpLp) \ + V(tRadiansOpLp) \ + V(tRandOpLp) \ + V(tRoundOpLp) \ + V(tSignOpLp) \ + V(tSinOpLp) \ + V(tSqrtOpLp) \ + V(tTanOpLp) \ + V(tFormatOpLp) \ + V(tLogOpLp) \ + V(tModOpLp) \ + V(tPowOpLp) \ + V(tTruncateOpLp) \ + V(tConvOpLp) \ + V(tRowNumberOpLpOpRp) \ + V(tRankOpLpOpRp) \ + V(tDenseRankOpLpOpRp) \ + V(tCumeDistOpLpOpRp) \ + V(tPercentRankOpLpOpRp) \ + V(tNtileOpLp) \ + V(tLeadOpLp) \ + V(tLagOpLp) \ + V(tFirstValueOpLp) \ + V(tLastValueOpLp) \ + V(tNthValueOpLp) \ + V(tRespectNulls) \ + V(tIgnoreNulls) \ + V(tFromFirst) \ + V(tFromLast) \ + V(tAvgOpLp) \ + V(tBitAndOpLp) \ + V(tBitOrOpLp) \ + V(tBitXorOpLp) \ + V(tCountOpLpOpMulOpRp) \ + V(tCountOpLp) \ + V(tCountOpLpDistinct) \ + V(tMinOpLp) \ + V(tMaxOpLp) \ + V(tSumOpLp) \ + V(tStdOpLp) \ + V(tStddevSampOpLp) \ + V(tVarianceOpLp) \ + V(tVarSampOpLp) \ + V(tGroupConcatOpLp) \ + V(tSeparator) \ + V(tOver) \ + V(tIfOpLp) \ + V(tIfnullOpLp) \ + V(tNullifOpLp) \ + V(tEnd) \ + V(tCase) \ + V(tThen) \ + V(tWhen) \ + V(tElse) \ + V(tCastOpLp) \ + V(tConvertOpLp) \ + V(tNchar) \ + V(tNull) \ + V(tFalse) \ + V(tTrue) \ + V(tOpDot) \ + V(tOpGreatereq) \ + V(tOpGreaterthan) \ + V(tOpLesseq) \ + V(tOpLessthan) \ + V(tOpNotequal) \ + V(tAny) \ + V(tSome) \ + V(tIn) \ + V(tNotIn) \ + V(tIconst) \ + V(tFconst) \ + V(tSconst) \ + V(tIdent) \ + +#define IRNUMBER 273 + +#endif \ No newline at end of file diff --git a/include/instantiate.h b/include/instantiate.h new file mode 100755 index 0000000..9e9afa3 --- /dev/null +++ b/include/instantiate.h @@ -0,0 +1,459 @@ +#ifndef __INSTANTIATE_H__ +#define __INSTANTIATE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ast.h" +#include "mutate.h" + +using namespace std; + +typedef uint8_t name_t; + +#define UNREFERENCE static_cast(-1) +#define COLUMNNAMEMAX 64 +#define RESERVEDCOLUMNNAME (COLUMNNAMEMAX - 1) + +#define LIMITMIN 1 +#define LIMITMAX 128 +#define OFFSETMIN 0 +#define OFFSETMAX 16 + +#define DEFAULTROWNUMBER -1 +#define DEFAULTCOLUMNNUMBER -1 + +#define MINSTRINGLENGTH 0 +#define MAXSTRINGLENGTH 64 + +#define CAPACITYBASE 80 +#define MAXCAPACITY 120 +#define CAPACITYGROWTHRATE 1.02 +#define TIMETHRESHOLD (3600 * 1000) + +#ifdef DEBUG +#define NT_check(ir, type) (assert(ir->type_ == type), ir) +#else +#define NT_check(ir, type) ir +#endif + +enum class IdentifierType { + iTable, + iColumn, + iWindow, + iIndex, + iConstraint, + iView +}; +enum class ColumnStatus { + csNormal, + csDuplication +}; +enum class ColumnType { + ctNull, ctInt, ctTinyInt, ctSmallInt, ctMediumInt, ctBigInt, + ctReal, ctDouble, ctFloat, ctDecimal, ctNumeric, ctFixed, + ctBool, ctBoolean, + ctChar, ctBinary, ctVarchar, ctVarbinary, ctLongVarbinary, + ctTinyBlob, ctMediumBlob, ctLongBlob, ctBlob, + ctTinyText, ctMediumText, ctLongText, ctText +}; +enum class TypeCompatibility { + tcNoCompatibility, + tcWeakCompatibility, + tcFullyCompatibility +}; +enum class IndexType { + itNormal, + itFunctional +}; +enum class ConstraintType { + ctNull, + ctUnique, + ctPrimaryKey, + ctCheck, + ctForeignKey +}; +enum class StmtLocation { + slNotSubquery, + slSubquery, + slCTE, + slRecursiveCTE, + slRecursivePart1, + slRecursivePart2, + slTableReference, + slWhereClause, + slGroupClause, + slTargetList, + slHavingClause, + slWindowClause, + slOrderClause +}; +enum class WindowStatus { + wsNoInherit, + wsInherit, + wsCantBeInherited, + wsWithOrder +}; +enum class ColumnBasicType { + ctString, + ctNumber, + ctBool +}; + +class Table; +class SelectStmtInfo; +class Instantiator; +class Constraint; + +class Column { +public: + Column(name_t name, ColumnType type); + Column(Column* column); + + bool notNull_ = false; + bool hasDefault_ = false; + bool isVisible_ = true; + name_t identifierName_; + ColumnStatus duplicated_ = ColumnStatus::csNormal; + ColumnType columnType_; + Table* parentTable_ = nullptr; + + static vector> compatibility_; + static map typeTranslation_; + static map typeToBasicType_; + + static void instantiate(); +}; + +class Index { +public: + Index(name_t name); + + name_t identifierName_; + Constraint* constraint_ = nullptr; + map columns_; +}; + +class Constraint { +public: + Constraint(name_t name, ConstraintType type); + + name_t identifierName_; + ConstraintType constraintType_; + Index* index_ = nullptr; + map columns_; + map> refToOtherColumns_; +}; + +class Table { +public: + Table(name_t name, IdentifierType identifierType, SelectStmtInfo* inSelectStmtInfo); + Table(Table* otherTable, SelectStmtInfo* inSelectStmtInfo); + ~Table(); + + bool isSubQuery_ = false; + bool isTemporary_ = false; + bool hasPrimaryKey_ = false; + name_t identifierName_; + IdentifierType identifierType_; + SelectStmtInfo* inSelectStmtInfo_ = nullptr; + + vector acceColumnNames_; + vector columns_; + + vector indexes_; + + vector constraints_; + map> refFromOtherColumns_; + + bool check_drop_table(); + bool exist_duplicated_column(); + void update_duplicationInfo(vector& duplicationInfo); + void update_duplicatedColumns(vector& duplicationInfo); + + bool column_drop_check(Column* column); + Column* get_column(); + Column* get_column(ColumnType type); + name_t get_acce_column_name(); + vector get_column_seq(); + void add_column_first(Column* column); + bool add_column(Column* column, Column* afterColumn = nullptr); + void move_column_first(Column* column); + bool move_column(Column* column, Column* afterColumn); + bool drop_column(Column* column); + + void column_rename(Column* column, name_t oldName, name_t newName); + + Index* get_index(); + vector get_index(Column* column); + bool add_index(Index* index); + bool drop_index(Index* index); + + Constraint* get_constraint(); + vector get_constraint(Column* column); + bool add_constraint(Constraint* constraint, Index* index = nullptr); + bool drop_constraint(Constraint* constraint); + bool set_references(Column* curTableColumn, Column* otherTableColumn); + bool remove_references(Column* curTableColumn, Column* otherTableColumn); + + bool remove_column_name(name_t name); + bool add_column_name(name_t name); + void drop_index(Column* column); + void drop_constraint(Column* column); + + bool index_drop_check(Index* index); + + bool constraint_drop_check(Constraint* constraint); +}; + +class SelectStmtInfo { +public: + SelectStmtInfo(StmtLocation location, int rowNumber, int columnNumber); + ~SelectStmtInfo(); + + bool hasAggregate = false; + + int columnNumber_; + int rowNumber_; + + name_t recursiveCteName_ = UNREFERENCE; + Table* recursiveCte_ = nullptr; + + StmtLocation location_; + + vector innerCteTables_; + vector outCteTables_; + + vector outReferences_; + + vector usedOutColumns_; + vector usedInnerColumns_; + + vector usedTables_; + vector acceColumns_; + + map windowStatusRecord_; + + bool is_duplicated_table(Table* table); + bool exist_duplicated_column(vector& v1, vector& v2); + bool has_column_limit(); + bool has_row_limit(); + + void add_used_table(Table* table); + void clear_local_info(); + void clear_cte(); + + void update_acceColumns(); + void update_acceColumns(vector& usedTables, vector& duplicationInfo); + + void add_usedInnerColumns(Column* column); + void add_usedOutColumns(Column* column); + void add_out_usedColumns(vector& usedColumns); + void add_all_usedColumns(vector& usedColumns); + +private: + vector duplicationInfo_ = vector(COLUMNNAMEMAX, 0); +}; + +class GlobalStatusManger { +public: + ~GlobalStatusManger(); + + stack selectInfoStack_; + + vector ignoreInnerUsedColumns_ = { StmtLocation::slWhereClause, StmtLocation::slTableReference, StmtLocation::slOrderClause }; + + void reset_status(); + + void push_selectInfo(StmtLocation location, int rowNumber, int columnNumber); + void pop_selectInfo(); + + SelectStmtInfo* get_cur_selectInfo(); + + int get_acce_table_number(); + Table* get_acce_table(int index); + vector get_acce_table(IdentifierType type); + + name_t get_new_table_name(); + name_t get_new_view_name(); + name_t get_new_window_name(); + name_t get_new_index_name(); + name_t get_new_constraint_name(); + + bool add_table(Table* table); + bool drop_table(Table* table); + bool drop_table(name_t name, IdentifierType type); + +private: + name_t totalTableName_ = 0; + name_t totalViewName_ = 0; + name_t totalWindowName_ = 0; + name_t totalIndexName_ = 0; + name_t totalConstraintName_ = 0; + + vector globalTables_; + + void pop_cur_selectInfo(); +}; + +class IRTrim { +public: + IRTrim(Instantiator* instantiator); + ~IRTrim(); + + void instantiate_simple_limit(); + void instantiate_simple_column_list(); + void instantiate_simple_alias(); + void instantiate_simple_expr_root(); + void instantiate_simple_expr_root_true(); + void instantiate_simple_expr_root_list(); + void instantiate_simple_simple_select_item_list(); + void instantiate_simple_window_spec(); + void instantiate_simple_index_name(); + void instantiate_simple_constraint_name(); + void instantiate_simple_key_part(); + void instantiate_simple_key_part_list(); + void instantiate_simple_table_element(); + void instantiate_simple_values(); + + IR* get_expr_root_columnref(Column* column); + void set_recursive_limit(IR* expr_root); + + IR* simple_limit_ = nullptr; + IR* simple_column_list_ = nullptr; + IR* simple_alias_ = nullptr; + IR* simple_expr_root_ = nullptr; + IR* simple_expr_root_true_ = nullptr; + IR* simple_expr_root_list_ = nullptr; + IR* simple_select_item_list_ = nullptr; + IR* simple_window_spec_ = nullptr; + IR* simple_index_name_ = nullptr; + IR* simple_constraint_name_ = nullptr; + IR* simple_key_part_ = nullptr; + IR* simple_key_part_list_ = nullptr; + IR* simple_table_element_ = nullptr; + IR* simple_values_ = nullptr; + + IR* expr_root_columnref_ = nullptr; + +private: + vector simpleIR_; + Instantiator* instantiator_; +}; + +class ExprInstantiator { +public: + ExprInstantiator(Instantiator* m): instantiator_(m){} + + vector usedColumnsBuffer_; + + void instantiate_expr_root(IR* expr_root, vector& acceColumns, StmtLocation location); + void instantiate_expr(IR* expr, vector& acceColumns, StmtLocation location); + void instantiate_simple_expr(IR* simple_expr, vector& acceColumns, StmtLocation location); + void instantiate_type_cast(IR* type_cast, vector& acceColumns, StmtLocation location); + void instantiate_function(IR* function, vector& acceColumns, StmtLocation location); + void instantiate_aggregate_function(IR* aggregate_function, vector& acceColumns, StmtLocation location); + void instantiate_window_function(IR* window_function, vector& acceColumns, StmtLocation location); + + long int get_random_integer(long int min = LONG_MIN, long int max = LONG_MAX); + double get_random_float(int min = INT_MIN, int max = INT_MAX); + string get_random_string(int minLength, int maxLength); + +private: + Instantiator* instantiator_; + vector ignoreSimpleExpr_ = { IRTYPE::kSimpleExpr, IRTYPE::kCaseExpr, IRTYPE::kExpr, IRTYPE::kLiteral }; +}; + +class Instantiator { +public: + Instantiator(); + ~Instantiator(); + + chrono::time_point startTime; + unsigned int get_duration_ms(); + + bool instantaite_sql(IR* root); + int calc_capacity(IR* root); + int calc_node(IR* root); + + IRTrim* IRTrim_; + GlobalStatusManger* globalStatusManger_; + ExprInstantiator* exprInstantiator_; + + void instantiate_parse_toplevel(IR* parse_toplevel); + + void instantiate_alter_table_stmt(IR* alter_table_stmt); + void instantiate_alter_list_item(IR* alter_list_item, Table* table); + + void instantiate_insert_stmt(IR* insert_stmt); + void instantiate_values_list(IR* values_list, int chosenColumnNumber); + void instantiate_values(IR* values, int chosenColumnNumber); + + void instantiate_update_stmt(IR* update_stmt); + int instantiate_update_list(IR* update_list, Table* table); + + void instantiate_delete_stmt(IR* delete_stmt); + + void instantiate_drop_table_or_view_stmt(IR* drop_table_stmt, IdentifierType type); + + void instantiate_drop_index_stmt(IR* drop_index_stmt); + + void instantiate_create_index_stmt(IR* create_index_stmt); + + void instantiate_create_view_stmt(IR* create_view_stmt); + + void instantiate_create_table_stmt(IR* create_table_stmt); + void instantiate_table_element_list(IR* table_element_list, Table* table); + pair> instantiate_column_def(IR* column_def, Table* table); + ColumnType instantiate_data_type(IR* data_type); + void instantiate_column_attribute(IR* column_attribute, Column* column, Table* table); + map instantiate_key_list_with_expression(IR* key_list_with_expression, Table* table, ConstraintType type); + bool instantiate_table_constraint_def_index(IR* table_constraint_def, Table* table); + bool instantiate_table_constraint_def_key(IR* table_constraint_def, Table* table); + bool instantiate_table_constraint_def_check(IR* table_constraint_def, Table* table); + bool instantiate_table_constraint_def_foreign_key(IR* table_constraint_def, Table* table); + + void instantiate_select_stmt(IR* select_stmt); + Table* instantiate_query_expression(IR* subquery, StmtLocation location, int rowNumber, int columnNumber); + Table* instantiate_query_expression(IR* query_expression); + Table* instantiate_query_primary(IR* query_primary); + Table* instanitate_union(IR* query_expression_body); + + void instantiate_with_clause(IR* with_clause); + void instantiate_order_clause(IR* order_clause); + void instantiate_limit_clause(IR* limit_clause); + + Table* instantiate_select_item_list(IR* select_item_list); + void instantiate_from_clause(IR* from_clause); + vector instantiate_table_reference(IR* table_reference); + Table* instantiate_single_table(IR* single_table); + Table* instantiate_derived_table(IR* derived_table); + vector instantiate_joined_table(IR* joined_table); + void instantiate_where_clause(IR* where_clause); + void instantiate_group_clause(IR* group_clause); + void instantiate_having_clause(IR* having_clause); + void instantiate_window_clause(IR* window_clause); + void instantiate_window_definition(IR* window_definition); + WindowStatus instantiate_window_spec(IR* window_spec); + + void instantiate_column_list(IR* column_list, vector& columns); + void instantiate_column_list(IR* column_list, vector& columns); + void instantiate_key_list(IR* key_list, vector& columns); + void instantiate_ident(IR* identifier_name, IdentifierType type, name_t name); + + bool check_foreign_key(Table* table, vector& curTableColumn, vector& otherTableColumn); +}; + +#endif diff --git a/include/mutate.h b/include/mutate.h new file mode 100755 index 0000000..800c8a4 --- /dev/null +++ b/include/mutate.h @@ -0,0 +1,207 @@ +#ifndef __MUTATOR_H__ +#define __MUTATOR_H__ + + +#include "ast.h" +#include "define.h" +#include "instantiate.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TOPNUMBER 10 + +#ifdef CLOSEMETHOD +#define IRTYPEUPDATETHRESHOLD UINT_MAX +#define IRINFOUPDATETHRESHOLD UINT_MAX +#else +#define IRTYPEUPDATETHRESHOLD 100 +#define IRINFOUPDATETHRESHOLD 100 +#endif + +#define REWARDINCREMENT 10 +#define REWARDNEWCOVERAGE 10 + +#define TIMETHRESHOLD (3600 * 1000) + +#ifdef BALANCE +#define MUTATENUMBER 2 +#endif + +using namespace std; + +#define ERRORINDEX USHRT_MAX + +enum class MutateOperator { + moReplace, + moInsert, + moDelete +}; + +double get_random_double(int min, int max); + +typedef struct { + unsigned char stmt_; + unsigned char inSubquery_; + unsigned short int clause_; + unsigned short int parentIRType_; + unsigned short int parentIRItem_; +} IRContextS; + +class IRInfomation { +public: + IRInfomation(int prefix, int left, int middle, int right, int suffix); + IRInfomation(IR* root); + + bool operator!=(IRInfomation* info); + + TERMINAL prefix_; + IRTYPE left_; + TERMINAL middle_; + IRTYPE right_; + TERMINAL suffix_; +}; + +class IRInfoManger { +public: + IRInfoManger(); + ~IRInfoManger(); + + IRTYPE curIRType_; + + vector IRInfoChosenCount_; + + void create_new_context(IRContextS* context); + + void update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward); + + void add_IRInfomation(IRInfomation* info); + IRInfomation* get_IRInfomation(unsigned short int index); + vector get_IRInfo_index(IRContextS* context, double heat); + + unsigned short int get_index_of_IRInfo(IR* root); + + string print_IRInformation_status(); + +private: + vector IRInfomation_; + unordered_map>> contextDependentCount_; +}; + +class OperatorManger { +public: + OperatorManger(); + ~OperatorManger(); + + IRTYPE curIRType_; + vector OpInfoChosenCount_; + vector OpInfoFailedCount_; + + void create_new_context(IRContextS* context); + vector get_OpInfo_index(IRContextS* context, double heat); + MutateOperator get_operator(unsigned short int index); + + void update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward); + + string print_OperatorInformation_status(); + +private: + vector OperatorInfomation_; + map>> contextDependentCount_; +}; + +class InputInfo { +public: + InputInfo(); + ~InputInfo(); + + IRTYPE MutateIRType_; + unsigned short int MutateIRInfoItem_; + unsigned short int MutateOperatorItem_; + + IRContextS MutateContext_; + IR* input_; +}; + +class Mutator { +public: + Mutator(); + + ~Mutator(); + + unsigned int failedMutate_ = 0; + unsigned int totalMutate_ = 0; + + IR* IR_parser(const char* sql); + + vector mutate_all(const char* sql); + + void update_status(InputInfo* input, unsigned int execStatus, bool isValid); + + bool init_IR_library(string filePath); + bool init_IR_config_info(string filePath); + + void print_information(string outputPath); + +private: + static vector stmtIRType_; + static vector clauseIRType_; + + chrono::time_point startTime; + + unsigned int seedCount_ = 0; + vector mutateNumber_; + + map IRInfo_; + map OpInfo_; + map> IRTypeCount_; + + set not_mutatable_types_; + set sql_hash_; + + map> IR_library_; + map> IR_library_hash_; + + void free_IR_library(); + void free_IR_config_info(); + + uint64_t hash(string& sql); + vector get_all_files_in_dir(const char* dir_name); + + ParseToplevel* parser(const char* sql); + + bool add_ir_to_library(IR* root); + bool add_ir_to_library_no_deepcopy(IR* root); + + IR* get_ir_from_library(IRTYPE type); + + void extract_struct(IR* root); + + vector mutate(IR* root, IRContextS context, double heat); + IR* get_new_tree(IR* oldIRRoot, IR* curIR, IR* newIR); + + unsigned int get_duration_ms(); + double get_cur_heat(); + unsigned int get_cur_reward(); + + void print_IRType_information(string outputPath); + void print_IRInfo_information(string outputPath); + void print_Mutate_number(string outputPath); + void print_OpInfo_information(string outputPath); + + vector original_mutate(IR* root, IRContextS context, double heat); + + IR* strategy_delete(IR* root); + IR* strategy_insert(IR* root); + IR* strategy_replace(IR* root); + + IR* check_sql(string& sql); +}; + +#endif diff --git a/parser/Makefile b/parser/Makefile new file mode 100755 index 0000000..f2be1cd --- /dev/null +++ b/parser/Makefile @@ -0,0 +1,30 @@ +# bison's version is too old on OSX, allow user to pass in custom path +BISON?=bison +FLEX?=flex + +#BISON_VERSION=$(shell $(BISON) --version | head -n 1 | grep -o '[0-9]\.[0-9]\+') +#BISON_VERSION_SUPPORTED=$(shell echo $(BISON_VERSION) \>= 3.0 | bc) +#ifneq ($(BISON_VERSION_SUPPORTED), 1) +#$(error Bison version $(BISON_VERSION) not supported. If you are using OS X, `bison` uses the system default instead of the brew version. Run BISON=/usr/local/opt/bison/bin/bison make) +#endif + +#FLEX_VERSION=$(shell $(FLEX) --version | head -n 1 | grep -o '[0-9]\.[0-9]\+') +#FLEX_VERSION_SUPPORTED=$(shell echo $(FLEX_VERSION) \>= 2.6 | bc) +#ifneq ($(FLEX_VERSION_SUPPORTED), 1) +#$(error Flex version $(FLEX_VERSION) not supported. If you are using OS X, `flex` uses the system default instead of the brew version. Run FLEX=/usr/local/opt/flex/bin/flex make) +#endif + +all: bison_parser.cpp flex_lexer.cpp + +bison_parser.cpp: bison.y + $(BISON) bison.y --output=bison_parser.cpp --defines=bison_parser.h --verbose -Wconflicts-rr + +flex_lexer.cpp: flex.l + $(FLEX) flex.l + +clean: + rm -f bison_parser.cpp flex_lexer.cpp bison_parser.h flex_lexer.h *.output + +# Tests if the parser builds correctly and doesn't contain conflicts. +test: + ! $(BISON) bison_parser.y -v --output=conflict_test.cpp 2>&1 | grep "conflict" >/tmp/2 diff --git a/parser/bison.y b/parser/bison.y new file mode 100755 index 0000000..ec2eef9 --- /dev/null +++ b/parser/bison.y @@ -0,0 +1,4451 @@ +%{ +#include "bison_parser.h" +#include "flex_lexer.h" +#include +#include +int yyerror(YYLTYPE* llocp, ParseToplevel * result, yyscan_t scanner, const char *msg) { /*printf("%s\n", msg);*/ return 0; } +%} +%code requires { +#include "../include/ast.h" +#include "../include/instantiate.h" +#include "parser_typedef.h" +} +%define api.prefix {ff_} +%define parse.error verbose +%define api.pure full +%define api.token.prefix {SQL_} +%locations + +%initial-action { + @$.first_column = 0; + @$.last_column = 0; + @$.first_line = 0; + @$.last_line = 0; + @$.total_column = 0; + @$.string_length = 0; +}; + +%lex-param { yyscan_t scanner } +%parse-param { ParseToplevel* result } +%parse-param { yyscan_t scanner } + +%union FF_STYPE{ + long long_value; + char* charp_value; + double double_value; + + ParseToplevel* parse_toplevel_t; + Stmtmulti* stmtmulti_t; + Stmt* stmt_t; + DeleteStmt* delete_stmt_t; + OptDeleteOptions* opt_delete_options_t; + DeleteOptions* delete_options_t; + DeleteOption* delete_option_t; + AlterTableStmt* alter_table_stmt_t; + AlterList* alter_list_t; + AlterListItem* alter_list_item_t; + OptPlace* opt_place_t; + DropIndexStmt* drop_index_stmt_t; + DropTableStmt* drop_table_stmt_t; + IfExists* if_exists_t; + TableList* table_list_t; + DropViewStmt* drop_view_stmt_t; + UpdateStmt* update_stmt_t; + OptSimpleLimit* opt_simple_limit_t; + OptWithClause* opt_with_clause_t; + OptLowPriority* opt_low_priority_t; + InsertStmt* insert_stmt_t; + InsertQueryExpression* insert_query_expression_t; + InsertFromConstructor* insert_from_constructor_t; + ValuesList* values_list_t; + RowValue* row_value_t; + OptValues* opt_values_t; + Values* values_t; + ExprOrDefault* expr_or_default_t; + OptValuesReference* opt_values_reference_t; + OptInsertUpdateList* opt_insert_update_list_t; + UpdateList* update_list_t; + UpdateElem* update_elem_t; + InsertLockOption* insert_lock_option_t; + OptIgnore* opt_ignore_t; + CreateIndexStmt* create_index_stmt_t; + OptUnique* opt_unique_t; + CreateViewStmt* create_view_stmt_t; + OptOrReplace* opt_or_replace_t; + OptViewAlgorithm* opt_view_algorithm_t; + CreateTableStmt* create_table_stmt_t; + OptTemporary* opt_temporary_t; + OptIfNotExists* opt_if_not_exists_t; + OptDuplicateAsQe* opt_duplicate_as_qe_t; + DuplicateAsQe* duplicate_as_qe_t; + Duplicate* duplicate_t; + TableElementList* table_element_list_t; + TableElement* table_element_t; + ColumnDef* column_def_t; + FieldDef* field_def_t; + DataType* data_type_t; + StringType* string_type_t; + BoolType* bool_type_t; + NumberType* number_type_t; + NumericType* numeric_type_t; + RealType* real_type_t; + OptPrecision* opt_precision_t; + IntType* int_type_t; + OptFieldOptions* opt_field_options_t; + FieldOptionList* field_option_list_t; + FieldOption* field_option_t; + OptColumnAttributeList* opt_column_attribute_list_t; + ColumnAttributeList* column_attribute_list_t; + ColumnAttribute* column_attribute_t; + DefaultAttribute* default_attribute_t; + NotNull* not_null_t; + Visibility* visibility_t; + OptConstraintName* opt_constraint_name_t; + CheckConstraint* check_constraint_t; + TableConstraintDef* table_constraint_def_t; + References* references_t; + OptOnUpdateDelete* opt_on_update_delete_t; + OnUpdateOption* on_update_option_t; + KeyList* key_list_t; + KeyListWithExpression* key_list_with_expression_t; + KeyPartWithExpression* key_part_with_expression_t; + KeyPart* key_part_t; + ConstraintKeyType* constraint_key_type_t; + OptIndexName* opt_index_name_t; + SelectStmt* select_stmt_t; + QueryExpression* query_expression_t; + QueryExpressionBody* query_expression_body_t; + QueryPrimary* query_primary_t; + QuerySpecification* query_specification_t; + OptWindowClause* opt_window_clause_t; + WindowDefinitionList* window_definition_list_t; + WindowDefinition* window_definition_t; + WindowSpec* window_spec_t; + WindowSpecDetails* window_spec_details_t; + OptExistingWindowName* opt_existing_window_name_t; + OptPartitionClause* opt_partition_clause_t; + OptWindowOrderByClause* opt_window_order_by_clause_t; + OrderList* order_list_t; + OrderExpr* order_expr_t; + OptOrderingDirection* opt_ordering_direction_t; + OptWindowFrameClause* opt_window_frame_clause_t; + WindowFrameUnits* window_frame_units_t; + WindowFrameExtent* window_frame_extent_t; + WindowFrameStart* window_frame_start_t; + WindowFrameBetween* window_frame_between_t; + WindowFrameBound* window_frame_bound_t; + OptHavingClause* opt_having_clause_t; + OptGroupClause* opt_group_clause_t; + OlapOpt* olap_opt_t; + OptWhereClause* opt_where_clause_t; + WhereClause* where_clause_t; + OptFromClause* opt_from_clause_t; + FromClause* from_clause_t; + TableReferenceList* table_reference_list_t; + TableReference* table_reference_t; + TableFactor* table_factor_t; + TableReferenceListParens* table_reference_list_parens_t; + JoinedTableParens* joined_table_parens_t; + DerivedTable* derived_table_t; + OptColumnList* opt_column_list_t; + ColumnList* column_list_t; + Subquery* subquery_t; + SingleTable* single_table_t; + OptAlias* opt_alias_t; + JoinedTable* joined_table_t; + InnerJoinType* inner_join_type_t; + NaturalJoinType* natural_join_type_t; + OptInner* opt_inner_t; + OptOuter* opt_outer_t; + OuterJoinType* outer_join_type_t; + SelectItemList* select_item_list_t; + SelectItem* select_item_t; + TableWild* table_wild_t; + OptSelectOptions* opt_select_options_t; + SelectOptionList* select_option_list_t; + SelectOption* select_option_t; + QueryExpressionParens* query_expression_parens_t; + OptUnionOption* opt_union_option_t; + OptOrderClause* opt_order_clause_t; + OrderClause* order_clause_t; + OptLimitClause* opt_limit_clause_t; + LimitClause* limit_clause_t; + LimitOptions* limit_options_t; + WithClause* with_clause_t; + WithList* with_list_t; + CommonTableExpr* common_table_expr_t; + ExprRootList* expr_root_list_t; + ExprRoot* expr_root_t; + Expr* expr_t; + BoolPri* bool_pri_t; + Predicate* predicate_t; + BitExpr* bit_expr_t; + SimpleExpr* simple_expr_t; + Function* function_t; + StringFunction* string_function_t; + MathFunction* math_function_t; + WindowFunction* window_function_t; + OptNullTreatment* opt_null_treatment_t; + OptFromFirstLast* opt_from_first_last_t; + OptLeadLagInfo* opt_lead_lag_info_t; + LeadLagInfo* lead_lag_info_t; + AggregateFunction* aggregate_function_t; + OptGconcatSeparator* opt_gconcat_separator_t; + OptDistinct* opt_distinct_t; + OptWindowingClause* opt_windowing_clause_t; + WindowingClause* windowing_clause_t; + WindowNameOrSpec* window_name_or_spec_t; + ControlFunction* control_function_t; + CaseExpr* case_expr_t; + WhenClasueList* when_clasue_list_t; + WhenList* when_list_t; + OptExpr* opt_expr_t; + OptElse* opt_else_t; + TypeCast* type_cast_t; + CastType* cast_type_t; + FloatOptions* float_options_t; + Precision* precision_t; + OptFieldLength* opt_field_length_t; + FieldLength* field_length_t; + Literal* literal_t; + Columnref* columnref_t; + CompOp* comp_op_t; + AllSubquery* all_subquery_t; + InSubquery* in_subquery_t; + ExprList* expr_list_t; + Iconst* iconst_t; + Fconst* fconst_t; + Sconst* sconst_t; + Ident* ident_t; + Alias* alias_t; + ColumnName* column_name_t; + WindowName* window_name_t; + TableName* table_name_t; + ConstraintName* constraint_name_t; + IndexName* index_name_t; + ViewName* view_name_t; +} + +%token OP_SEMI FROM DELETE QUICK LOW_PRIORITY IGNORE ALTER TABLE OP_COMMA +%token ADD COLUMN OP_RP OP_LP CHANGE MODIFY DROP FOREIGN KEY PRIMARY +%token INDEX CHECK CONSTRAINT SET DEFAULT RENAME TO AFTER FIRST ON +%token IF EXISTS VIEW UPDATE LIMIT INTO INSERT VALUES AS DUPLICATE +%token OP_EQUAL DELAYED HIGH_PRIORITY CREATE UNIQUE OR REPLACE ALGORITHM UNDEFINED MERGE +%token TEMPTABLE TEMPORARY NOT CHAR BINARY VARCHAR VARBINARY LONG TINYBLOB MEDIUMBLOB +%token LONGBLOB BLOB TINYTEXT MEDIUMTEXT LONGTEXT TEXT BOOL BOOLEAN FLOAT DECIMAL +%token NUMERIC FIXED REAL DOUBLE INT TINYINT SMALLINT MEDIUMINT BIGINT SIGNED +%token UNSIGNED ZEROFILL NULL VISIBLE INVISIBLE REFERENCES CASCADE NO ACTION UNION +%token EXCEPT INTERSECT SELECT WINDOW PARTITION BY ORDER ASC DESC ROWS +%token RANGE UNBOUNDED PRECEDING CURRENT ROW AND BETWEEN FOLLOWING HAVING GROUP +%token WITH ROLLUP WHERE LATERAL USING JOIN INNER CROSS STRAIGHT_JOIN NATURAL +%token RIGHT LEFT OUTER OP_MUL OP_DOT SQL_NO_CACHE DISTINCT SQL_SMALL_RESULT SQL_BIG_RESULT SQL_BUFFER_RESULT +%token SQL_CALC_FOUND_ROWS ALL RECURSIVE XOR IS TRUE FALSE UNKNOWN IN SOUNDS +%token LIKE REGEXP OP_OR OP_AND OP_SHL OP_SHR OP_ADD OP_SUB OP_DIVIDE OP_MOD +%token OP_XOR OP_NOT ASCII BIN BIT_LENGTH CHAR_LENGTH LENGTH LOWER LTRIM OCT +%token ORD QUOTE REVERSE RTRIM SPACE TRIM LEADING TRAILING UNHEX UPPER +%token FIND_IN_SET INSTR LOCATE REPEAT SUBSTRING EXPORT_SET LPAD RPAD SUBSTRING_INDEX CONCAT +%token CONCAT_WS ELT FIELD MAKE_SET PI RAND ABS ACOS ASIN ATAN +%token CEILING COS COT DEGREES EXP FLOOR HEX LN RADIANS ROUND +%token SIGN SIN SQRT TAN FORMAT LOG MOD POW TRUNCATE CONV +%token ROW_NUMBER RANK DENSE_RANK CUME_DIST PERCENT_RANK NTILE LEAD LAG FIRST_VALUE LAST_VALUE +%token NTH_VALUE RESPECT NULLS LAST AVG BIT_AND BIT_OR BIT_XOR COUNT MIN +%token MAX SUM STD STDDEV_SAMP VARIANCE VAR_SAMP GROUP_CONCAT SEPARATOR OVER IFNULL +%token NULLIF END CASE THEN WHEN ELSE CAST CONVERT NCHAR OP_GREATEREQ +%token OP_GREATERTHAN OP_LESSEQ OP_LESSTHAN OP_NOTEQUAL ANY SOME + +%token IDENT +%token ICONST +%token FCONST +%token SCONST + +%type parse_toplevel +%type stmtmulti +%type stmt +%type delete_stmt +%type opt_delete_options +%type delete_options +%type delete_option +%type alter_table_stmt +%type alter_list +%type alter_list_item +%type opt_place +%type drop_index_stmt +%type drop_table_stmt +%type if_exists +%type table_list +%type drop_view_stmt +%type update_stmt +%type opt_simple_limit +%type opt_with_clause +%type opt_low_priority +%type insert_stmt +%type insert_query_expression +%type insert_from_constructor +%type values_list +%type row_value +%type opt_values +%type values +%type expr_or_default +%type opt_values_reference +%type opt_insert_update_list +%type update_list +%type update_elem +%type insert_lock_option +%type opt_ignore +%type create_index_stmt +%type opt_unique +%type create_view_stmt +%type opt_or_replace +%type opt_view_algorithm +%type create_table_stmt +%type opt_temporary +%type opt_if_not_exists +%type opt_duplicate_as_qe +%type duplicate_as_qe +%type duplicate +%type table_element_list +%type table_element +%type column_def +%type field_def +%type data_type +%type string_type +%type bool_type +%type number_type +%type numeric_type +%type real_type +%type opt_precision +%type int_type +%type opt_field_options +%type field_option_list +%type field_option +%type opt_column_attribute_list +%type column_attribute_list +%type column_attribute +%type default_attribute +%type not_null +%type visibility +%type opt_constraint_name +%type check_constraint +%type table_constraint_def +%type references +%type opt_on_update_delete +%type on_update_option +%type key_list +%type key_list_with_expression +%type key_part_with_expression +%type key_part +%type constraint_key_type +%type opt_index_name +%type select_stmt +%type query_expression +%type query_expression_body +%type query_primary +%type query_specification +%type opt_window_clause +%type window_definition_list +%type window_definition +%type window_spec +%type window_spec_details +%type opt_existing_window_name +%type opt_partition_clause +%type opt_window_order_by_clause +%type order_list +%type order_expr +%type opt_ordering_direction +%type opt_window_frame_clause +%type window_frame_units +%type window_frame_extent +%type window_frame_start +%type window_frame_between +%type window_frame_bound +%type opt_having_clause +%type opt_group_clause +%type olap_opt +%type opt_where_clause +%type where_clause +%type opt_from_clause +%type from_clause +%type table_reference_list +%type table_reference +%type table_factor +%type table_reference_list_parens +%type joined_table_parens +%type derived_table +%type opt_column_list +%type column_list +%type subquery +%type single_table +%type opt_alias +%type joined_table +%type inner_join_type +%type natural_join_type +%type opt_inner +%type opt_outer +%type outer_join_type +%type select_item_list +%type select_item +%type table_wild +%type opt_select_options +%type select_option_list +%type select_option +%type query_expression_parens +%type opt_union_option +%type opt_order_clause +%type order_clause +%type opt_limit_clause +%type limit_clause +%type limit_options +%type with_clause +%type with_list +%type common_table_expr +%type expr_root_list +%type expr_root +%type expr +%type bool_pri +%type predicate +%type bit_expr +%type simple_expr +%type function +%type string_function +%type math_function +%type window_function +%type opt_null_treatment +%type opt_from_first_last +%type opt_lead_lag_info +%type lead_lag_info +%type aggregate_function +%type opt_gconcat_separator +%type opt_distinct +%type opt_windowing_clause +%type windowing_clause +%type window_name_or_spec +%type control_function +%type case_expr +%type when_clasue_list +%type when_list +%type opt_expr +%type opt_else +%type type_cast +%type cast_type +%type float_options +%type precision +%type opt_field_length +%type field_length +%type literal +%type columnref +%type comp_op +%type all_subquery +%type in_subquery +%type expr_list +%type iconst +%type fconst +%type sconst +%type ident +%type alias +%type column_name +%type window_name +%type table_name +%type constraint_name +%type index_name +%type view_name + +%left UNION EXCEPT +%left INTERSECT +%left CONDITIONLESS_JOIN +%left JOIN INNER CROSS STRAIGHT_JOIN NATURAL LEFT RIGHT ON USING +%left OR +%left XOR +%left AND +%left BETWEEN CASE WHEN THEN ELSE +%left OP_GREATERTHAN OP_LESSTHAN OP_GREATEREQ OP_LESSEQ OP_NOTEQUAL OP_EQUAL IS LIKE REGEXP IN +%left OP_OR +%left OP_AND +%left OP_SHL OP_SHR +%left OP_ADD OP_SUB +%left OP_MUL OP_MOD OP_DIVIDE +%left OP_XOR +%left UMINUS OP_NOT +%right NOT +%left SUBQUERY_AS_EXPR +%left OP_RP OP_LP + +%destructor{ + free( ($$) ); +} + +%destructor{ + +} + +%destructor { if($$!=NULL)$$->deep_delete(); } <*> + +%start parse_toplevel + +%% + +parse_toplevel: + stmtmulti { + $$ = result; + $$->case_idx_ = CASE0; + + $$->stmtmulti_ = $1; + + $$ = NULL; + } + ; + +stmtmulti: + stmt OP_SEMI stmtmulti { + $$ = new Stmtmulti(); + $$->case_idx_ = CASE0; + + $$->stmt_ = $1; + $$->stmtmulti_ = $3; + } + |stmt OP_SEMI { + $$ = new Stmtmulti(); + $$->case_idx_ = CASE1; + + $$->stmt_ = $1; + } + ; + +stmt: + create_table_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE0; + + $$->create_table_stmt_ = $1; + } + |create_view_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE1; + + $$->create_view_stmt_ = $1; + } + |create_index_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE2; + + $$->create_index_stmt_ = $1; + } + |select_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE3; + + $$->select_stmt_ = $1; + } + |drop_index_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE4; + + $$->drop_index_stmt_ = $1; + } + |drop_table_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE5; + + $$->drop_table_stmt_ = $1; + } + |drop_view_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE6; + + $$->drop_view_stmt_ = $1; + } + |delete_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE7; + + $$->delete_stmt_ = $1; + } + |update_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE8; + + $$->update_stmt_ = $1; + } + |insert_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE9; + + $$->insert_stmt_ = $1; + } + |alter_table_stmt { + $$ = new Stmt(); + $$->case_idx_ = CASE10; + + $$->alter_table_stmt_ = $1; + } + ; + +delete_stmt: + opt_with_clause DELETE opt_delete_options FROM table_name opt_alias opt_where_clause opt_order_clause opt_simple_limit { + $$ = new DeleteStmt(); + $$->case_idx_ = CASE0; + + $$->opt_with_clause_ = $1; + $$->opt_delete_options_ = $3; + $$->table_name_ = $5; + $$->opt_alias_ = $6; + $$->opt_where_clause_ = $7; + $$->opt_order_clause_ = $8; + $$->opt_simple_limit_ = $9; + } + |opt_with_clause DELETE opt_delete_options table_list FROM table_reference_list opt_where_clause { + $$ = new DeleteStmt(); + $$->case_idx_ = CASE1; + + $$->opt_with_clause_ = $1; + $$->opt_delete_options_ = $3; + $$->table_list_ = $4; + $$->table_reference_list_ = $6; + $$->opt_where_clause_ = $7; + } + ; + +opt_delete_options: + { + $$ = new OptDeleteOptions(); + $$->case_idx_ = CASE0; + } + |delete_options { + $$ = new OptDeleteOptions(); + $$->case_idx_ = CASE1; + + $$->delete_options_ = $1; + } + ; + +delete_options: + delete_option { + $$ = new DeleteOptions(); + $$->case_idx_ = CASE0; + + $$->delete_option_ = $1; + } + |delete_option delete_options { + $$ = new DeleteOptions(); + $$->case_idx_ = CASE1; + + $$->delete_option_ = $1; + $$->delete_options_ = $2; + } + ; + +delete_option: + QUICK { + $$ = new DeleteOption(); + $$->case_idx_ = CASE0; + } + |LOW_PRIORITY { + $$ = new DeleteOption(); + $$->case_idx_ = CASE1; + } + |IGNORE { + $$ = new DeleteOption(); + $$->case_idx_ = CASE2; + } + ; + +alter_table_stmt: + ALTER TABLE table_name alter_list { + $$ = new AlterTableStmt(); + $$->case_idx_ = CASE0; + + $$->table_name_ = $3; + $$->alter_list_ = $4; + } + ; + +alter_list: + alter_list_item { + $$ = new AlterList(); + $$->case_idx_ = CASE0; + + $$->alter_list_item_ = $1; + } + |alter_list_item OP_COMMA alter_list { + $$ = new AlterList(); + $$->case_idx_ = CASE1; + + $$->alter_list_item_ = $1; + $$->alter_list_ = $3; + } + ; + +alter_list_item: + ADD COLUMN column_name field_def opt_place { + $$ = new AlterListItem(); + $$->case_idx_ = CASE0; + + $$->column_name_1_ = $3; + $$->field_def_ = $4; + $$->opt_place_ = $5; + } + |ADD COLUMN OP_LP table_element_list OP_RP { + $$ = new AlterListItem(); + $$->case_idx_ = CASE1; + + $$->table_element_list_ = $4; + } + |ADD table_constraint_def { + $$ = new AlterListItem(); + $$->case_idx_ = CASE2; + + $$->table_constraint_def_ = $2; + } + |CHANGE COLUMN column_name column_name field_def opt_place { + $$ = new AlterListItem(); + $$->case_idx_ = CASE3; + + $$->column_name_1_ = $3; + $$->column_name_2_ = $4; + $$->field_def_ = $5; + $$->opt_place_ = $6; + } + |MODIFY COLUMN column_name field_def opt_place { + $$ = new AlterListItem(); + $$->case_idx_ = CASE4; + + $$->column_name_1_ = $3; + $$->field_def_ = $4; + $$->opt_place_ = $5; + } + |DROP COLUMN column_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE5; + + $$->column_name_1_ = $3; + } + |DROP FOREIGN KEY constraint_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE6; + + $$->constraint_name_ = $4; + } + |DROP PRIMARY KEY { + $$ = new AlterListItem(); + $$->case_idx_ = CASE7; + } + |DROP INDEX index_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE8; + + $$->index_name_1_ = $3; + } + |DROP CHECK constraint_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE9; + + $$->constraint_name_ = $3; + } + |DROP CONSTRAINT constraint_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE10; + + $$->constraint_name_ = $3; + } + |ALTER COLUMN column_name SET DEFAULT OP_LP expr_root OP_RP { + $$ = new AlterListItem(); + $$->case_idx_ = CASE11; + + $$->column_name_1_ = $3; + $$->expr_root_ = $7; + } + |ALTER COLUMN column_name DROP DEFAULT { + $$ = new AlterListItem(); + $$->case_idx_ = CASE12; + + $$->column_name_1_ = $3; + } + |ALTER COLUMN column_name SET visibility { + $$ = new AlterListItem(); + $$->case_idx_ = CASE13; + + $$->column_name_1_ = $3; + $$->visibility_ = $5; + } + |ALTER INDEX index_name visibility { + $$ = new AlterListItem(); + $$->case_idx_ = CASE14; + + $$->index_name_1_ = $3; + $$->visibility_ = $4; + } + |RENAME TO table_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE15; + + $$->table_name_ = $3; + } + |RENAME INDEX index_name TO index_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE16; + + $$->index_name_1_ = $3; + $$->index_name_2_ = $5; + } + |RENAME COLUMN column_name TO column_name { + $$ = new AlterListItem(); + $$->case_idx_ = CASE17; + + $$->column_name_1_ = $3; + $$->column_name_2_ = $5; + } + ; + +opt_place: + { + $$ = new OptPlace(); + $$->case_idx_ = CASE0; + } + |AFTER column_name { + $$ = new OptPlace(); + $$->case_idx_ = CASE1; + + $$->column_name_ = $2; + } + |FIRST { + $$ = new OptPlace(); + $$->case_idx_ = CASE2; + } + ; + +drop_index_stmt: + DROP INDEX index_name ON table_name { + $$ = new DropIndexStmt(); + $$->case_idx_ = CASE0; + + $$->index_name_ = $3; + $$->table_name_ = $5; + } + ; + +drop_table_stmt: + DROP TABLE if_exists table_list { + $$ = new DropTableStmt(); + $$->case_idx_ = CASE0; + + $$->if_exists_ = $3; + $$->table_list_ = $4; + } + ; + +if_exists: + { + $$ = new IfExists(); + $$->case_idx_ = CASE0; + } + |IF EXISTS { + $$ = new IfExists(); + $$->case_idx_ = CASE1; + } + ; + +table_list: + table_name { + $$ = new TableList(); + $$->case_idx_ = CASE0; + + $$->table_name_ = $1; + } + |table_name OP_COMMA table_list { + $$ = new TableList(); + $$->case_idx_ = CASE1; + + $$->table_name_ = $1; + $$->table_list_ = $3; + } + ; + +drop_view_stmt: + DROP VIEW if_exists table_list { + $$ = new DropViewStmt(); + $$->case_idx_ = CASE0; + + $$->if_exists_ = $3; + $$->table_list_ = $4; + } + ; + +update_stmt: + opt_with_clause UPDATE opt_low_priority opt_ignore table_reference_list SET update_list opt_where_clause opt_order_clause opt_simple_limit { + $$ = new UpdateStmt(); + $$->case_idx_ = CASE0; + + $$->opt_with_clause_ = $1; + $$->opt_low_priority_ = $3; + $$->opt_ignore_ = $4; + $$->table_reference_list_ = $5; + $$->update_list_ = $7; + $$->opt_where_clause_ = $8; + $$->opt_order_clause_ = $9; + $$->opt_simple_limit_ = $10; + } + ; + +opt_simple_limit: + { + $$ = new OptSimpleLimit(); + $$->case_idx_ = CASE0; + } + |LIMIT iconst { + $$ = new OptSimpleLimit(); + $$->case_idx_ = CASE1; + + $$->iconst_ = $2; + } + ; + +opt_with_clause: + { + $$ = new OptWithClause(); + $$->case_idx_ = CASE0; + } + |with_clause { + $$ = new OptWithClause(); + $$->case_idx_ = CASE1; + + $$->with_clause_ = $1; + } + ; + +opt_low_priority: + { + $$ = new OptLowPriority(); + $$->case_idx_ = CASE0; + } + |LOW_PRIORITY { + $$ = new OptLowPriority(); + $$->case_idx_ = CASE1; + } + ; + +insert_stmt: + INSERT insert_lock_option opt_ignore INTO table_name insert_from_constructor opt_values_reference opt_insert_update_list { + $$ = new InsertStmt(); + $$->case_idx_ = CASE0; + + $$->insert_lock_option_ = $2; + $$->opt_ignore_ = $3; + $$->table_name_ = $5; + $$->insert_from_constructor_ = $6; + $$->opt_values_reference_ = $7; + $$->opt_insert_update_list_ = $8; + } + |INSERT insert_lock_option opt_ignore INTO table_name SET update_list opt_values_reference opt_insert_update_list { + $$ = new InsertStmt(); + $$->case_idx_ = CASE1; + + $$->insert_lock_option_ = $2; + $$->opt_ignore_ = $3; + $$->table_name_ = $5; + $$->update_list_ = $7; + $$->opt_values_reference_ = $8; + $$->opt_insert_update_list_ = $9; + } + |INSERT insert_lock_option opt_ignore INTO table_name insert_query_expression opt_insert_update_list { + $$ = new InsertStmt(); + $$->case_idx_ = CASE2; + + $$->insert_lock_option_ = $2; + $$->opt_ignore_ = $3; + $$->table_name_ = $5; + $$->insert_query_expression_ = $6; + $$->opt_insert_update_list_ = $7; + } + ; + +insert_query_expression: + query_expression { + $$ = new InsertQueryExpression(); + $$->case_idx_ = CASE0; + + $$->query_expression_ = $1; + } + |OP_LP column_list OP_RP query_expression { + $$ = new InsertQueryExpression(); + $$->case_idx_ = CASE1; + + $$->column_list_ = $2; + $$->query_expression_ = $4; + } + ; + +insert_from_constructor: + VALUES values_list { + $$ = new InsertFromConstructor(); + $$->case_idx_ = CASE0; + + $$->values_list_ = $2; + } + |OP_LP column_list OP_RP VALUES values_list { + $$ = new InsertFromConstructor(); + $$->case_idx_ = CASE1; + + $$->column_list_ = $2; + $$->values_list_ = $5; + } + ; + +values_list: + row_value { + $$ = new ValuesList(); + $$->case_idx_ = CASE0; + + $$->row_value_ = $1; + } + |row_value OP_COMMA values_list { + $$ = new ValuesList(); + $$->case_idx_ = CASE1; + + $$->row_value_ = $1; + $$->values_list_ = $3; + } + ; + +row_value: + OP_LP opt_values OP_RP { + $$ = new RowValue(); + $$->case_idx_ = CASE0; + + $$->opt_values_ = $2; + } + ; + +opt_values: + { + $$ = new OptValues(); + $$->case_idx_ = CASE0; + } + |values { + $$ = new OptValues(); + $$->case_idx_ = CASE1; + + $$->values_ = $1; + } + ; + +values: + expr_or_default { + $$ = new Values(); + $$->case_idx_ = CASE0; + + $$->expr_or_default_ = $1; + } + |expr_or_default OP_COMMA values { + $$ = new Values(); + $$->case_idx_ = CASE1; + + $$->expr_or_default_ = $1; + $$->values_ = $3; + } + ; + +expr_or_default: + expr_root { + $$ = new ExprOrDefault(); + $$->case_idx_ = CASE0; + + $$->expr_root_ = $1; + } + |DEFAULT { + $$ = new ExprOrDefault(); + $$->case_idx_ = CASE1; + } + ; + +opt_values_reference: + { + $$ = new OptValuesReference(); + $$->case_idx_ = CASE0; + } + |AS table_name opt_column_list { + $$ = new OptValuesReference(); + $$->case_idx_ = CASE1; + + $$->table_name_ = $2; + $$->opt_column_list_ = $3; + } + ; + +opt_insert_update_list: + { + $$ = new OptInsertUpdateList(); + $$->case_idx_ = CASE0; + } + |ON DUPLICATE KEY UPDATE update_list { + $$ = new OptInsertUpdateList(); + $$->case_idx_ = CASE1; + + $$->update_list_ = $5; + } + ; + +update_list: + update_elem { + $$ = new UpdateList(); + $$->case_idx_ = CASE0; + + $$->update_elem_ = $1; + } + |update_elem OP_COMMA update_list { + $$ = new UpdateList(); + $$->case_idx_ = CASE1; + + $$->update_elem_ = $1; + $$->update_list_ = $3; + } + ; + +update_elem: + columnref OP_EQUAL expr_or_default { + $$ = new UpdateElem(); + $$->case_idx_ = CASE0; + + $$->columnref_ = $1; + $$->expr_or_default_ = $3; + } + ; + +insert_lock_option: + { + $$ = new InsertLockOption(); + $$->case_idx_ = CASE0; + } + |LOW_PRIORITY { + $$ = new InsertLockOption(); + $$->case_idx_ = CASE1; + } + |DELAYED { + $$ = new InsertLockOption(); + $$->case_idx_ = CASE2; + } + |HIGH_PRIORITY { + $$ = new InsertLockOption(); + $$->case_idx_ = CASE3; + } + ; + +opt_ignore: + { + $$ = new OptIgnore(); + $$->case_idx_ = CASE0; + } + |IGNORE { + $$ = new OptIgnore(); + $$->case_idx_ = CASE1; + } + ; + +create_index_stmt: + CREATE opt_unique INDEX index_name ON table_name OP_LP key_list_with_expression OP_RP { + $$ = new CreateIndexStmt(); + $$->case_idx_ = CASE0; + + $$->opt_unique_ = $2; + $$->index_name_ = $4; + $$->table_name_ = $6; + $$->key_list_with_expression_ = $8; + } + ; + +opt_unique: + { + $$ = new OptUnique(); + $$->case_idx_ = CASE0; + } + |UNIQUE { + $$ = new OptUnique(); + $$->case_idx_ = CASE1; + } + ; + +create_view_stmt: + CREATE opt_or_replace opt_view_algorithm VIEW view_name opt_column_list AS query_expression { + $$ = new CreateViewStmt(); + $$->case_idx_ = CASE0; + + $$->opt_or_replace_ = $2; + $$->opt_view_algorithm_ = $3; + $$->view_name_ = $5; + $$->opt_column_list_ = $6; + $$->query_expression_ = $8; + } + ; + +opt_or_replace: + { + $$ = new OptOrReplace(); + $$->case_idx_ = CASE0; + } + |OR REPLACE { + $$ = new OptOrReplace(); + $$->case_idx_ = CASE1; + } + ; + +opt_view_algorithm: + { + $$ = new OptViewAlgorithm(); + $$->case_idx_ = CASE0; + } + |ALGORITHM OP_EQUAL UNDEFINED { + $$ = new OptViewAlgorithm(); + $$->case_idx_ = CASE1; + } + |ALGORITHM OP_EQUAL MERGE { + $$ = new OptViewAlgorithm(); + $$->case_idx_ = CASE2; + } + |ALGORITHM OP_EQUAL TEMPTABLE { + $$ = new OptViewAlgorithm(); + $$->case_idx_ = CASE3; + } + ; + +create_table_stmt: + CREATE opt_temporary TABLE opt_if_not_exists table_name OP_LP table_element_list OP_RP opt_duplicate_as_qe { + $$ = new CreateTableStmt(); + $$->case_idx_ = CASE0; + + $$->opt_temporary_ = $2; + $$->opt_if_not_exists_ = $4; + $$->table_name_ = $5; + $$->table_element_list_ = $7; + $$->opt_duplicate_as_qe_ = $9; + } + |CREATE opt_temporary TABLE opt_if_not_exists table_name duplicate_as_qe { + $$ = new CreateTableStmt(); + $$->case_idx_ = CASE1; + + $$->opt_temporary_ = $2; + $$->opt_if_not_exists_ = $4; + $$->table_name_ = $5; + $$->duplicate_as_qe_ = $6; + } + ; + +opt_temporary: + { + $$ = new OptTemporary(); + $$->case_idx_ = CASE0; + } + |TEMPORARY { + $$ = new OptTemporary(); + $$->case_idx_ = CASE1; + } + ; + +opt_if_not_exists: + { + $$ = new OptIfNotExists(); + $$->case_idx_ = CASE0; + } + |IF NOT EXISTS { + $$ = new OptIfNotExists(); + $$->case_idx_ = CASE1; + } + ; + +opt_duplicate_as_qe: + { + $$ = new OptDuplicateAsQe(); + $$->case_idx_ = CASE0; + } + |duplicate_as_qe { + $$ = new OptDuplicateAsQe(); + $$->case_idx_ = CASE1; + + $$->duplicate_as_qe_ = $1; + } + ; + +duplicate_as_qe: + duplicate AS query_expression { + $$ = new DuplicateAsQe(); + $$->case_idx_ = CASE0; + + $$->duplicate_ = $1; + $$->query_expression_ = $3; + } + |AS query_expression { + $$ = new DuplicateAsQe(); + $$->case_idx_ = CASE1; + + $$->query_expression_ = $2; + } + ; + +duplicate: + REPLACE { + $$ = new Duplicate(); + $$->case_idx_ = CASE0; + } + |IGNORE { + $$ = new Duplicate(); + $$->case_idx_ = CASE1; + } + ; + +table_element_list: + table_element { + $$ = new TableElementList(); + $$->case_idx_ = CASE0; + + $$->table_element_ = $1; + } + |table_element OP_COMMA table_element_list { + $$ = new TableElementList(); + $$->case_idx_ = CASE1; + + $$->table_element_ = $1; + $$->table_element_list_ = $3; + } + ; + +table_element: + column_def { + $$ = new TableElement(); + $$->case_idx_ = CASE0; + + $$->column_def_ = $1; + } + |table_constraint_def { + $$ = new TableElement(); + $$->case_idx_ = CASE1; + + $$->table_constraint_def_ = $1; + } + ; + +column_def: + column_name field_def { + $$ = new ColumnDef(); + $$->case_idx_ = CASE0; + + $$->column_name_ = $1; + $$->field_def_ = $2; + } + ; + +field_def: + data_type opt_column_attribute_list { + $$ = new FieldDef(); + $$->case_idx_ = CASE0; + + $$->data_type_ = $1; + $$->opt_column_attribute_list_ = $2; + } + ; + +data_type: + number_type { + $$ = new DataType(); + $$->case_idx_ = CASE0; + + $$->number_type_ = $1; + } + |bool_type { + $$ = new DataType(); + $$->case_idx_ = CASE1; + + $$->bool_type_ = $1; + } + |string_type { + $$ = new DataType(); + $$->case_idx_ = CASE2; + + $$->string_type_ = $1; + } + ; + +string_type: + CHAR opt_field_length { + $$ = new StringType(); + $$->case_idx_ = CASE0; + + $$->opt_field_length_ = $2; + } + |BINARY opt_field_length { + $$ = new StringType(); + $$->case_idx_ = CASE1; + + $$->opt_field_length_ = $2; + } + |VARCHAR field_length { + $$ = new StringType(); + $$->case_idx_ = CASE2; + + $$->field_length_ = $2; + } + |VARBINARY field_length { + $$ = new StringType(); + $$->case_idx_ = CASE3; + + $$->field_length_ = $2; + } + |LONG VARBINARY { + $$ = new StringType(); + $$->case_idx_ = CASE4; + } + |TINYBLOB { + $$ = new StringType(); + $$->case_idx_ = CASE5; + } + |MEDIUMBLOB { + $$ = new StringType(); + $$->case_idx_ = CASE6; + } + |LONGBLOB { + $$ = new StringType(); + $$->case_idx_ = CASE7; + } + |BLOB opt_field_length { + $$ = new StringType(); + $$->case_idx_ = CASE8; + + $$->opt_field_length_ = $2; + } + |TINYTEXT { + $$ = new StringType(); + $$->case_idx_ = CASE9; + } + |MEDIUMTEXT { + $$ = new StringType(); + $$->case_idx_ = CASE10; + } + |LONGTEXT { + $$ = new StringType(); + $$->case_idx_ = CASE11; + } + |TEXT { + $$ = new StringType(); + $$->case_idx_ = CASE12; + } + ; + +bool_type: + BOOL { + $$ = new BoolType(); + $$->case_idx_ = CASE0; + } + |BOOLEAN { + $$ = new BoolType(); + $$->case_idx_ = CASE1; + } + ; + +number_type: + int_type opt_field_options { + $$ = new NumberType(); + $$->case_idx_ = CASE0; + + $$->int_type_ = $1; + $$->opt_field_options_ = $2; + } + |real_type opt_precision opt_field_options { + $$ = new NumberType(); + $$->case_idx_ = CASE1; + + $$->real_type_ = $1; + $$->opt_precision_ = $2; + $$->opt_field_options_ = $3; + } + |numeric_type float_options opt_field_options { + $$ = new NumberType(); + $$->case_idx_ = CASE2; + + $$->numeric_type_ = $1; + $$->float_options_ = $2; + $$->opt_field_options_ = $3; + } + ; + +numeric_type: + FLOAT { + $$ = new NumericType(); + $$->case_idx_ = CASE0; + } + |DECIMAL { + $$ = new NumericType(); + $$->case_idx_ = CASE1; + } + |NUMERIC { + $$ = new NumericType(); + $$->case_idx_ = CASE2; + } + |FIXED { + $$ = new NumericType(); + $$->case_idx_ = CASE3; + } + ; + +real_type: + REAL { + $$ = new RealType(); + $$->case_idx_ = CASE0; + } + |DOUBLE { + $$ = new RealType(); + $$->case_idx_ = CASE1; + } + ; + +opt_precision: + { + $$ = new OptPrecision(); + $$->case_idx_ = CASE0; + } + |precision { + $$ = new OptPrecision(); + $$->case_idx_ = CASE1; + + $$->precision_ = $1; + } + ; + +int_type: + INT { + $$ = new IntType(); + $$->case_idx_ = CASE0; + } + |TINYINT { + $$ = new IntType(); + $$->case_idx_ = CASE1; + } + |SMALLINT { + $$ = new IntType(); + $$->case_idx_ = CASE2; + } + |MEDIUMINT { + $$ = new IntType(); + $$->case_idx_ = CASE3; + } + |BIGINT { + $$ = new IntType(); + $$->case_idx_ = CASE4; + } + ; + +opt_field_options: + { + $$ = new OptFieldOptions(); + $$->case_idx_ = CASE0; + } + |field_option_list { + $$ = new OptFieldOptions(); + $$->case_idx_ = CASE1; + + $$->field_option_list_ = $1; + } + ; + +field_option_list: + field_option { + $$ = new FieldOptionList(); + $$->case_idx_ = CASE0; + + $$->field_option_ = $1; + } + |field_option field_option_list { + $$ = new FieldOptionList(); + $$->case_idx_ = CASE1; + + $$->field_option_ = $1; + $$->field_option_list_ = $2; + } + ; + +field_option: + SIGNED { + $$ = new FieldOption(); + $$->case_idx_ = CASE0; + } + |UNSIGNED { + $$ = new FieldOption(); + $$->case_idx_ = CASE1; + } + |ZEROFILL { + $$ = new FieldOption(); + $$->case_idx_ = CASE2; + } + ; + +opt_column_attribute_list: + { + $$ = new OptColumnAttributeList(); + $$->case_idx_ = CASE0; + } + |column_attribute_list { + $$ = new OptColumnAttributeList(); + $$->case_idx_ = CASE1; + + $$->column_attribute_list_ = $1; + } + ; + +column_attribute_list: + column_attribute { + $$ = new ColumnAttributeList(); + $$->case_idx_ = CASE0; + + $$->column_attribute_ = $1; + } + |column_attribute column_attribute_list { + $$ = new ColumnAttributeList(); + $$->case_idx_ = CASE1; + + $$->column_attribute_ = $1; + $$->column_attribute_list_ = $2; + } + ; + +column_attribute: + not_null { + $$ = new ColumnAttribute(); + $$->case_idx_ = CASE0; + + $$->not_null_ = $1; + } + |default_attribute { + $$ = new ColumnAttribute(); + $$->case_idx_ = CASE1; + + $$->default_attribute_ = $1; + } + |visibility { + $$ = new ColumnAttribute(); + $$->case_idx_ = CASE2; + + $$->visibility_ = $1; + } + ; + +default_attribute: + DEFAULT OP_LP expr_root OP_RP { + $$ = new DefaultAttribute(); + $$->case_idx_ = CASE0; + + $$->expr_root_ = $3; + } + ; + +not_null: + NOT NULL { + $$ = new NotNull(); + $$->case_idx_ = CASE0; + } + ; + +visibility: + VISIBLE { + $$ = new Visibility(); + $$->case_idx_ = CASE0; + } + |INVISIBLE { + $$ = new Visibility(); + $$->case_idx_ = CASE1; + } + ; + +opt_constraint_name: + { + $$ = new OptConstraintName(); + $$->case_idx_ = CASE0; + } + |CONSTRAINT constraint_name { + $$ = new OptConstraintName(); + $$->case_idx_ = CASE1; + + $$->constraint_name_ = $2; + } + ; + +check_constraint: + CHECK OP_LP expr_root OP_RP { + $$ = new CheckConstraint(); + $$->case_idx_ = CASE0; + + $$->expr_root_ = $3; + } + ; + +table_constraint_def: + INDEX opt_index_name OP_LP key_list_with_expression OP_RP { + $$ = new TableConstraintDef(); + $$->case_idx_ = CASE0; + + $$->opt_index_name_ = $2; + $$->key_list_with_expression_ = $4; + } + |opt_constraint_name constraint_key_type opt_index_name OP_LP key_list_with_expression OP_RP { + $$ = new TableConstraintDef(); + $$->case_idx_ = CASE1; + + $$->opt_constraint_name_ = $1; + $$->constraint_key_type_ = $2; + $$->opt_index_name_ = $3; + $$->key_list_with_expression_ = $5; + } + |opt_constraint_name check_constraint { + $$ = new TableConstraintDef(); + $$->case_idx_ = CASE2; + + $$->opt_constraint_name_ = $1; + $$->check_constraint_ = $2; + } + |opt_constraint_name FOREIGN KEY opt_index_name OP_LP key_list OP_RP references { + $$ = new TableConstraintDef(); + $$->case_idx_ = CASE3; + + $$->opt_constraint_name_ = $1; + $$->opt_index_name_ = $4; + $$->key_list_ = $6; + $$->references_ = $8; + } + ; + +references: + REFERENCES table_name OP_LP column_list OP_RP opt_on_update_delete { + $$ = new References(); + $$->case_idx_ = CASE0; + + $$->table_name_ = $2; + $$->column_list_ = $4; + $$->opt_on_update_delete_ = $6; + } + ; + +opt_on_update_delete: + { + $$ = new OptOnUpdateDelete(); + $$->case_idx_ = CASE0; + } + |ON UPDATE on_update_option { + $$ = new OptOnUpdateDelete(); + $$->case_idx_ = CASE1; + + $$->on_update_option_1_ = $3; + } + |ON DELETE on_update_option { + $$ = new OptOnUpdateDelete(); + $$->case_idx_ = CASE2; + + $$->on_update_option_1_ = $3; + } + |ON UPDATE on_update_option ON DELETE on_update_option { + $$ = new OptOnUpdateDelete(); + $$->case_idx_ = CASE3; + + $$->on_update_option_1_ = $3; + $$->on_update_option_2_ = $6; + } + |ON DELETE on_update_option ON UPDATE on_update_option { + $$ = new OptOnUpdateDelete(); + $$->case_idx_ = CASE4; + + $$->on_update_option_1_ = $3; + $$->on_update_option_2_ = $6; + } + ; + +on_update_option: + CASCADE { + $$ = new OnUpdateOption(); + $$->case_idx_ = CASE0; + } + |SET NULL { + $$ = new OnUpdateOption(); + $$->case_idx_ = CASE1; + } + |NO ACTION { + $$ = new OnUpdateOption(); + $$->case_idx_ = CASE2; + } + |SET DEFAULT { + $$ = new OnUpdateOption(); + $$->case_idx_ = CASE3; + } + ; + +key_list: + key_part { + $$ = new KeyList(); + $$->case_idx_ = CASE0; + + $$->key_part_ = $1; + } + |key_part OP_COMMA key_list { + $$ = new KeyList(); + $$->case_idx_ = CASE1; + + $$->key_part_ = $1; + $$->key_list_ = $3; + } + ; + +key_list_with_expression: + key_part_with_expression { + $$ = new KeyListWithExpression(); + $$->case_idx_ = CASE0; + + $$->key_part_with_expression_ = $1; + } + |key_part_with_expression OP_COMMA key_list_with_expression { + $$ = new KeyListWithExpression(); + $$->case_idx_ = CASE1; + + $$->key_part_with_expression_ = $1; + $$->key_list_with_expression_ = $3; + } + ; + +key_part_with_expression: + key_part { + $$ = new KeyPartWithExpression(); + $$->case_idx_ = CASE0; + + $$->key_part_ = $1; + } + |OP_LP expr_root OP_RP opt_ordering_direction { + $$ = new KeyPartWithExpression(); + $$->case_idx_ = CASE1; + + $$->expr_root_ = $2; + $$->opt_ordering_direction_ = $4; + } + ; + +key_part: + column_name opt_ordering_direction { + $$ = new KeyPart(); + $$->case_idx_ = CASE0; + + $$->column_name_ = $1; + $$->opt_ordering_direction_ = $2; + } + |column_name OP_LP iconst OP_RP opt_ordering_direction { + $$ = new KeyPart(); + $$->case_idx_ = CASE1; + + $$->column_name_ = $1; + $$->iconst_ = $3; + $$->opt_ordering_direction_ = $5; + } + ; + +constraint_key_type: + PRIMARY KEY { + $$ = new ConstraintKeyType(); + $$->case_idx_ = CASE0; + } + |UNIQUE { + $$ = new ConstraintKeyType(); + $$->case_idx_ = CASE1; + } + ; + +opt_index_name: + { + $$ = new OptIndexName(); + $$->case_idx_ = CASE0; + } + |index_name { + $$ = new OptIndexName(); + $$->case_idx_ = CASE1; + + $$->index_name_ = $1; + } + ; + +select_stmt: + query_expression { + $$ = new SelectStmt(); + $$->case_idx_ = CASE0; + + $$->query_expression_ = $1; + } + ; + +query_expression: + query_expression_body opt_order_clause opt_limit_clause { + $$ = new QueryExpression(); + $$->case_idx_ = CASE0; + + $$->query_expression_body_ = $1; + $$->opt_order_clause_ = $2; + $$->opt_limit_clause_ = $3; + } + |with_clause query_expression_body opt_order_clause opt_limit_clause { + $$ = new QueryExpression(); + $$->case_idx_ = CASE1; + + $$->with_clause_ = $1; + $$->query_expression_body_ = $2; + $$->opt_order_clause_ = $3; + $$->opt_limit_clause_ = $4; + } + ; + +query_expression_body: + query_primary { + $$ = new QueryExpressionBody(); + $$->case_idx_ = CASE0; + + $$->query_primary_ = $1; + } + |query_expression_parens %prec SUBQUERY_AS_EXPR { + $$ = new QueryExpressionBody(); + $$->case_idx_ = CASE1; + + $$->query_expression_parens_ = $1; + } + |query_expression_body UNION opt_union_option query_expression_body { + $$ = new QueryExpressionBody(); + $$->case_idx_ = CASE2; + + $$->query_expression_body_1_ = $1; + $$->opt_union_option_ = $3; + $$->query_expression_body_2_ = $4; + } + |query_expression_body EXCEPT opt_union_option query_expression_body { + $$ = new QueryExpressionBody(); + $$->case_idx_ = CASE3; + + $$->query_expression_body_1_ = $1; + $$->opt_union_option_ = $3; + $$->query_expression_body_2_ = $4; + } + |query_expression_body INTERSECT opt_union_option query_expression_body { + $$ = new QueryExpressionBody(); + $$->case_idx_ = CASE4; + + $$->query_expression_body_1_ = $1; + $$->opt_union_option_ = $3; + $$->query_expression_body_2_ = $4; + } + ; + +query_primary: + query_specification { + $$ = new QueryPrimary(); + $$->case_idx_ = CASE0; + + $$->query_specification_ = $1; + } + ; + +query_specification: + SELECT opt_select_options select_item_list opt_from_clause opt_where_clause opt_group_clause opt_having_clause opt_window_clause { + $$ = new QuerySpecification(); + $$->case_idx_ = CASE0; + + $$->opt_select_options_ = $2; + $$->select_item_list_ = $3; + $$->opt_from_clause_ = $4; + $$->opt_where_clause_ = $5; + $$->opt_group_clause_ = $6; + $$->opt_having_clause_ = $7; + $$->opt_window_clause_ = $8; + } + ; + +opt_window_clause: + { + $$ = new OptWindowClause(); + $$->case_idx_ = CASE0; + } + |WINDOW window_definition_list { + $$ = new OptWindowClause(); + $$->case_idx_ = CASE1; + + $$->window_definition_list_ = $2; + } + ; + +window_definition_list: + window_definition { + $$ = new WindowDefinitionList(); + $$->case_idx_ = CASE0; + + $$->window_definition_ = $1; + } + |window_definition OP_COMMA window_definition_list { + $$ = new WindowDefinitionList(); + $$->case_idx_ = CASE1; + + $$->window_definition_ = $1; + $$->window_definition_list_ = $3; + } + ; + +window_definition: + window_name AS window_spec { + $$ = new WindowDefinition(); + $$->case_idx_ = CASE0; + + $$->window_name_ = $1; + $$->window_spec_ = $3; + } + ; + +window_spec: + OP_LP window_spec_details OP_RP { + $$ = new WindowSpec(); + $$->case_idx_ = CASE0; + + $$->window_spec_details_ = $2; + } + ; + +window_spec_details: + opt_existing_window_name opt_partition_clause opt_window_order_by_clause opt_window_frame_clause { + $$ = new WindowSpecDetails(); + $$->case_idx_ = CASE0; + + $$->opt_existing_window_name_ = $1; + $$->opt_partition_clause_ = $2; + $$->opt_window_order_by_clause_ = $3; + $$->opt_window_frame_clause_ = $4; + } + ; + +opt_existing_window_name: + { + $$ = new OptExistingWindowName(); + $$->case_idx_ = CASE0; + } + |window_name { + $$ = new OptExistingWindowName(); + $$->case_idx_ = CASE1; + + $$->window_name_ = $1; + } + ; + +opt_partition_clause: + { + $$ = new OptPartitionClause(); + $$->case_idx_ = CASE0; + } + |PARTITION BY expr_root_list { + $$ = new OptPartitionClause(); + $$->case_idx_ = CASE1; + + $$->expr_root_list_ = $3; + } + ; + +opt_window_order_by_clause: + { + $$ = new OptWindowOrderByClause(); + $$->case_idx_ = CASE0; + } + |ORDER BY order_list { + $$ = new OptWindowOrderByClause(); + $$->case_idx_ = CASE1; + + $$->order_list_ = $3; + } + ; + +order_list: + order_expr { + $$ = new OrderList(); + $$->case_idx_ = CASE0; + + $$->order_expr_ = $1; + } + |order_expr OP_COMMA order_list { + $$ = new OrderList(); + $$->case_idx_ = CASE1; + + $$->order_expr_ = $1; + $$->order_list_ = $3; + } + ; + +order_expr: + expr_root opt_ordering_direction { + $$ = new OrderExpr(); + $$->case_idx_ = CASE0; + + $$->expr_root_ = $1; + $$->opt_ordering_direction_ = $2; + } + ; + +opt_ordering_direction: + { + $$ = new OptOrderingDirection(); + $$->case_idx_ = CASE0; + } + |ASC { + $$ = new OptOrderingDirection(); + $$->case_idx_ = CASE1; + } + |DESC { + $$ = new OptOrderingDirection(); + $$->case_idx_ = CASE2; + } + ; + +opt_window_frame_clause: + { + $$ = new OptWindowFrameClause(); + $$->case_idx_ = CASE0; + } + |window_frame_units window_frame_extent { + $$ = new OptWindowFrameClause(); + $$->case_idx_ = CASE1; + + $$->window_frame_units_ = $1; + $$->window_frame_extent_ = $2; + } + ; + +window_frame_units: + ROWS { + $$ = new WindowFrameUnits(); + $$->case_idx_ = CASE0; + } + |RANGE { + $$ = new WindowFrameUnits(); + $$->case_idx_ = CASE1; + } + ; + +window_frame_extent: + window_frame_start { + $$ = new WindowFrameExtent(); + $$->case_idx_ = CASE0; + + $$->window_frame_start_ = $1; + } + |window_frame_between { + $$ = new WindowFrameExtent(); + $$->case_idx_ = CASE1; + + $$->window_frame_between_ = $1; + } + ; + +window_frame_start: + UNBOUNDED PRECEDING { + $$ = new WindowFrameStart(); + $$->case_idx_ = CASE0; + } + |iconst PRECEDING { + $$ = new WindowFrameStart(); + $$->case_idx_ = CASE1; + + $$->iconst_ = $1; + } + |CURRENT ROW { + $$ = new WindowFrameStart(); + $$->case_idx_ = CASE2; + } + ; + +window_frame_between: + BETWEEN window_frame_start AND window_frame_bound { + $$ = new WindowFrameBetween(); + $$->case_idx_ = CASE0; + + $$->window_frame_start_ = $2; + $$->window_frame_bound_ = $4; + } + ; + +window_frame_bound: + window_frame_start { + $$ = new WindowFrameBound(); + $$->case_idx_ = CASE0; + + $$->window_frame_start_ = $1; + } + |UNBOUNDED FOLLOWING { + $$ = new WindowFrameBound(); + $$->case_idx_ = CASE1; + } + |iconst FOLLOWING { + $$ = new WindowFrameBound(); + $$->case_idx_ = CASE2; + + $$->iconst_ = $1; + } + ; + +opt_having_clause: + { + $$ = new OptHavingClause(); + $$->case_idx_ = CASE0; + } + |HAVING expr_root { + $$ = new OptHavingClause(); + $$->case_idx_ = CASE1; + + $$->expr_root_ = $2; + } + ; + +opt_group_clause: + { + $$ = new OptGroupClause(); + $$->case_idx_ = CASE0; + } + |GROUP BY expr_root_list olap_opt { + $$ = new OptGroupClause(); + $$->case_idx_ = CASE1; + + $$->expr_root_list_ = $3; + $$->olap_opt_ = $4; + } + ; + +olap_opt: + { + $$ = new OlapOpt(); + $$->case_idx_ = CASE0; + } + |WITH ROLLUP { + $$ = new OlapOpt(); + $$->case_idx_ = CASE1; + } + ; + +opt_where_clause: + { + $$ = new OptWhereClause(); + $$->case_idx_ = CASE0; + } + |where_clause { + $$ = new OptWhereClause(); + $$->case_idx_ = CASE1; + + $$->where_clause_ = $1; + } + ; + +where_clause: + WHERE expr_root { + $$ = new WhereClause(); + $$->case_idx_ = CASE0; + + $$->expr_root_ = $2; + } + ; + +opt_from_clause: + { + $$ = new OptFromClause(); + $$->case_idx_ = CASE0; + } + |from_clause { + $$ = new OptFromClause(); + $$->case_idx_ = CASE1; + + $$->from_clause_ = $1; + } + ; + +from_clause: + FROM table_reference_list { + $$ = new FromClause(); + $$->case_idx_ = CASE0; + + $$->table_reference_list_ = $2; + } + ; + +table_reference_list: + table_reference { + $$ = new TableReferenceList(); + $$->case_idx_ = CASE0; + + $$->table_reference_ = $1; + } + |table_reference OP_COMMA table_reference_list { + $$ = new TableReferenceList(); + $$->case_idx_ = CASE1; + + $$->table_reference_ = $1; + $$->table_reference_list_ = $3; + } + ; + +table_reference: + table_factor { + $$ = new TableReference(); + $$->case_idx_ = CASE0; + + $$->table_factor_ = $1; + } + |joined_table { + $$ = new TableReference(); + $$->case_idx_ = CASE1; + + $$->joined_table_ = $1; + } + ; + +table_factor: + single_table { + $$ = new TableFactor(); + $$->case_idx_ = CASE0; + + $$->single_table_ = $1; + } + |derived_table { + $$ = new TableFactor(); + $$->case_idx_ = CASE1; + + $$->derived_table_ = $1; + } + |joined_table_parens { + $$ = new TableFactor(); + $$->case_idx_ = CASE2; + + $$->joined_table_parens_ = $1; + } + |table_reference_list_parens { + $$ = new TableFactor(); + $$->case_idx_ = CASE3; + + $$->table_reference_list_parens_ = $1; + } + ; + +table_reference_list_parens: + OP_LP table_reference OP_COMMA table_reference_list OP_RP { + $$ = new TableReferenceListParens(); + $$->case_idx_ = CASE0; + + $$->table_reference_ = $2; + $$->table_reference_list_ = $4; + } + ; + +joined_table_parens: + OP_LP joined_table OP_RP { + $$ = new JoinedTableParens(); + $$->case_idx_ = CASE0; + + $$->joined_table_ = $2; + } + ; + +derived_table: + subquery AS alias opt_column_list { + $$ = new DerivedTable(); + $$->case_idx_ = CASE0; + + $$->subquery_ = $1; + $$->alias_ = $3; + $$->opt_column_list_ = $4; + } + |LATERAL subquery AS alias opt_column_list { + $$ = new DerivedTable(); + $$->case_idx_ = CASE1; + + $$->subquery_ = $2; + $$->alias_ = $4; + $$->opt_column_list_ = $5; + } + ; + +opt_column_list: + { + $$ = new OptColumnList(); + $$->case_idx_ = CASE0; + } + |OP_LP column_list OP_RP { + $$ = new OptColumnList(); + $$->case_idx_ = CASE1; + + $$->column_list_ = $2; + } + ; + +column_list: + column_name { + $$ = new ColumnList(); + $$->case_idx_ = CASE0; + + $$->column_name_ = $1; + } + |column_name OP_COMMA column_list { + $$ = new ColumnList(); + $$->case_idx_ = CASE1; + + $$->column_name_ = $1; + $$->column_list_ = $3; + } + ; + +subquery: + query_expression_parens %prec SUBQUERY_AS_EXPR { + $$ = new Subquery(); + $$->case_idx_ = CASE0; + + $$->query_expression_parens_ = $1; + } + ; + +single_table: + table_name opt_alias { + $$ = new SingleTable(); + $$->case_idx_ = CASE0; + + $$->table_name_ = $1; + $$->opt_alias_ = $2; + } + ; + +opt_alias: + { + $$ = new OptAlias(); + $$->case_idx_ = CASE0; + } + |AS alias { + $$ = new OptAlias(); + $$->case_idx_ = CASE1; + + $$->alias_ = $2; + } + ; + +joined_table: + table_reference inner_join_type table_reference ON expr_root { + $$ = new JoinedTable(); + $$->case_idx_ = CASE0; + + $$->table_reference_1_ = $1; + $$->inner_join_type_ = $2; + $$->table_reference_2_ = $3; + $$->expr_root_ = $5; + } + |table_reference inner_join_type table_reference USING OP_LP column_list OP_RP { + $$ = new JoinedTable(); + $$->case_idx_ = CASE1; + + $$->table_reference_1_ = $1; + $$->inner_join_type_ = $2; + $$->table_reference_2_ = $3; + $$->column_list_ = $6; + } + |table_reference outer_join_type table_reference ON expr_root { + $$ = new JoinedTable(); + $$->case_idx_ = CASE2; + + $$->table_reference_1_ = $1; + $$->outer_join_type_ = $2; + $$->table_reference_2_ = $3; + $$->expr_root_ = $5; + } + |table_reference outer_join_type table_reference USING OP_LP column_list OP_RP { + $$ = new JoinedTable(); + $$->case_idx_ = CASE3; + + $$->table_reference_1_ = $1; + $$->outer_join_type_ = $2; + $$->table_reference_2_ = $3; + $$->column_list_ = $6; + } + |table_reference inner_join_type table_reference %prec CONDITIONLESS_JOIN { + $$ = new JoinedTable(); + $$->case_idx_ = CASE4; + + $$->table_reference_1_ = $1; + $$->inner_join_type_ = $2; + $$->table_reference_2_ = $3; + } + |table_reference natural_join_type table_factor { + $$ = new JoinedTable(); + $$->case_idx_ = CASE5; + + $$->table_reference_1_ = $1; + $$->natural_join_type_ = $2; + $$->table_factor_ = $3; + } + ; + +inner_join_type: + JOIN { + $$ = new InnerJoinType(); + $$->case_idx_ = CASE0; + } + |INNER JOIN { + $$ = new InnerJoinType(); + $$->case_idx_ = CASE1; + } + |CROSS JOIN { + $$ = new InnerJoinType(); + $$->case_idx_ = CASE2; + } + |STRAIGHT_JOIN { + $$ = new InnerJoinType(); + $$->case_idx_ = CASE3; + } + ; + +natural_join_type: + NATURAL opt_inner JOIN { + $$ = new NaturalJoinType(); + $$->case_idx_ = CASE0; + + $$->opt_inner_ = $2; + } + |NATURAL RIGHT opt_outer JOIN { + $$ = new NaturalJoinType(); + $$->case_idx_ = CASE1; + + $$->opt_outer_ = $3; + } + |NATURAL LEFT opt_outer JOIN { + $$ = new NaturalJoinType(); + $$->case_idx_ = CASE2; + + $$->opt_outer_ = $3; + } + ; + +opt_inner: + { + $$ = new OptInner(); + $$->case_idx_ = CASE0; + } + |INNER { + $$ = new OptInner(); + $$->case_idx_ = CASE1; + } + ; + +opt_outer: + { + $$ = new OptOuter(); + $$->case_idx_ = CASE0; + } + |OUTER { + $$ = new OptOuter(); + $$->case_idx_ = CASE1; + } + ; + +outer_join_type: + LEFT opt_outer JOIN { + $$ = new OuterJoinType(); + $$->case_idx_ = CASE0; + + $$->opt_outer_ = $2; + } + |RIGHT opt_outer JOIN { + $$ = new OuterJoinType(); + $$->case_idx_ = CASE1; + + $$->opt_outer_ = $2; + } + ; + +select_item_list: + select_item { + $$ = new SelectItemList(); + $$->case_idx_ = CASE0; + + $$->select_item_ = $1; + } + |select_item OP_COMMA select_item_list { + $$ = new SelectItemList(); + $$->case_idx_ = CASE1; + + $$->select_item_ = $1; + $$->select_item_list_ = $3; + } + ; + +select_item: + table_wild { + $$ = new SelectItem(); + $$->case_idx_ = CASE0; + + $$->table_wild_ = $1; + } + |expr_root opt_alias { + $$ = new SelectItem(); + $$->case_idx_ = CASE1; + + $$->expr_root_ = $1; + $$->opt_alias_ = $2; + } + ; + +table_wild: + OP_MUL { + $$ = new TableWild(); + $$->case_idx_ = CASE0; + } + |table_name OP_DOT OP_MUL { + $$ = new TableWild(); + $$->case_idx_ = CASE1; + + $$->table_name_ = $1; + } + ; + +opt_select_options: + { + $$ = new OptSelectOptions(); + $$->case_idx_ = CASE0; + } + |select_option_list { + $$ = new OptSelectOptions(); + $$->case_idx_ = CASE1; + + $$->select_option_list_ = $1; + } + ; + +select_option_list: + select_option { + $$ = new SelectOptionList(); + $$->case_idx_ = CASE0; + + $$->select_option_ = $1; + } + |select_option select_option_list { + $$ = new SelectOptionList(); + $$->case_idx_ = CASE1; + + $$->select_option_ = $1; + $$->select_option_list_ = $2; + } + ; + +select_option: + SQL_NO_CACHE { + $$ = new SelectOption(); + $$->case_idx_ = CASE0; + } + |STRAIGHT_JOIN { + $$ = new SelectOption(); + $$->case_idx_ = CASE1; + } + |HIGH_PRIORITY { + $$ = new SelectOption(); + $$->case_idx_ = CASE2; + } + |DISTINCT { + $$ = new SelectOption(); + $$->case_idx_ = CASE3; + } + |SQL_SMALL_RESULT { + $$ = new SelectOption(); + $$->case_idx_ = CASE4; + } + |SQL_BIG_RESULT { + $$ = new SelectOption(); + $$->case_idx_ = CASE5; + } + |SQL_BUFFER_RESULT { + $$ = new SelectOption(); + $$->case_idx_ = CASE6; + } + |SQL_CALC_FOUND_ROWS { + $$ = new SelectOption(); + $$->case_idx_ = CASE7; + } + |ALL { + $$ = new SelectOption(); + $$->case_idx_ = CASE8; + } + ; + +query_expression_parens: + OP_LP query_expression_parens OP_RP { + $$ = new QueryExpressionParens(); + $$->case_idx_ = CASE0; + + $$->query_expression_parens_ = $2; + } + |OP_LP query_expression OP_RP { + $$ = new QueryExpressionParens(); + $$->case_idx_ = CASE1; + + $$->query_expression_ = $2; + } + ; + +opt_union_option: + { + $$ = new OptUnionOption(); + $$->case_idx_ = CASE0; + } + |DISTINCT { + $$ = new OptUnionOption(); + $$->case_idx_ = CASE1; + } + |ALL { + $$ = new OptUnionOption(); + $$->case_idx_ = CASE2; + } + ; + +opt_order_clause: + { + $$ = new OptOrderClause(); + $$->case_idx_ = CASE0; + } + |order_clause { + $$ = new OptOrderClause(); + $$->case_idx_ = CASE1; + + $$->order_clause_ = $1; + } + ; + +order_clause: + ORDER BY order_list { + $$ = new OrderClause(); + $$->case_idx_ = CASE0; + + $$->order_list_ = $3; + } + ; + +opt_limit_clause: + { + $$ = new OptLimitClause(); + $$->case_idx_ = CASE0; + } + |limit_clause { + $$ = new OptLimitClause(); + $$->case_idx_ = CASE1; + + $$->limit_clause_ = $1; + } + ; + +limit_clause: + LIMIT limit_options { + $$ = new LimitClause(); + $$->case_idx_ = CASE0; + + $$->limit_options_ = $2; + } + ; + +limit_options: + iconst { + $$ = new LimitOptions(); + $$->case_idx_ = CASE0; + + $$->iconst_1_ = $1; + } + |iconst OP_COMMA iconst { + $$ = new LimitOptions(); + $$->case_idx_ = CASE1; + + $$->iconst_1_ = $1; + $$->iconst_2_ = $3; + } + ; + +with_clause: + WITH with_list { + $$ = new WithClause(); + $$->case_idx_ = CASE0; + + $$->with_list_ = $2; + } + |WITH RECURSIVE with_list { + $$ = new WithClause(); + $$->case_idx_ = CASE1; + + $$->with_list_ = $3; + } + ; + +with_list: + common_table_expr { + $$ = new WithList(); + $$->case_idx_ = CASE0; + + $$->common_table_expr_ = $1; + } + |common_table_expr OP_COMMA with_list { + $$ = new WithList(); + $$->case_idx_ = CASE1; + + $$->common_table_expr_ = $1; + $$->with_list_ = $3; + } + ; + +common_table_expr: + table_name opt_column_list AS subquery { + $$ = new CommonTableExpr(); + $$->case_idx_ = CASE0; + + $$->table_name_ = $1; + $$->opt_column_list_ = $2; + $$->subquery_ = $4; + } + ; + +expr_root_list: + expr_root { + $$ = new ExprRootList(); + $$->case_idx_ = CASE0; + + $$->expr_root_ = $1; + } + |expr_root OP_COMMA expr_root_list { + $$ = new ExprRootList(); + $$->case_idx_ = CASE1; + + $$->expr_root_ = $1; + $$->expr_root_list_ = $3; + } + ; + +expr_root: + expr { + $$ = new ExprRoot(); + $$->case_idx_ = CASE0; + + $$->expr_ = $1; + } + ; + +expr: + expr OR expr { + $$ = new Expr(); + $$->case_idx_ = CASE0; + + $$->expr_1_ = $1; + $$->expr_2_ = $3; + } + |expr XOR expr { + $$ = new Expr(); + $$->case_idx_ = CASE1; + + $$->expr_1_ = $1; + $$->expr_2_ = $3; + } + |expr AND expr { + $$ = new Expr(); + $$->case_idx_ = CASE2; + + $$->expr_1_ = $1; + $$->expr_2_ = $3; + } + |NOT expr { + $$ = new Expr(); + $$->case_idx_ = CASE3; + + $$->expr_1_ = $2; + } + |bool_pri IS TRUE { + $$ = new Expr(); + $$->case_idx_ = CASE4; + + $$->bool_pri_ = $1; + } + |bool_pri IS NOT TRUE { + $$ = new Expr(); + $$->case_idx_ = CASE5; + + $$->bool_pri_ = $1; + } + |bool_pri IS FALSE { + $$ = new Expr(); + $$->case_idx_ = CASE6; + + $$->bool_pri_ = $1; + } + |bool_pri IS NOT FALSE { + $$ = new Expr(); + $$->case_idx_ = CASE7; + + $$->bool_pri_ = $1; + } + |bool_pri IS UNKNOWN { + $$ = new Expr(); + $$->case_idx_ = CASE8; + + $$->bool_pri_ = $1; + } + |bool_pri IS NOT UNKNOWN { + $$ = new Expr(); + $$->case_idx_ = CASE9; + + $$->bool_pri_ = $1; + } + |bool_pri { + $$ = new Expr(); + $$->case_idx_ = CASE10; + + $$->bool_pri_ = $1; + } + ; + +bool_pri: + bool_pri IS NULL { + $$ = new BoolPri(); + $$->case_idx_ = CASE0; + + $$->bool_pri_ = $1; + } + |bool_pri IS NOT NULL { + $$ = new BoolPri(); + $$->case_idx_ = CASE1; + + $$->bool_pri_ = $1; + } + |bool_pri comp_op predicate { + $$ = new BoolPri(); + $$->case_idx_ = CASE2; + + $$->bool_pri_ = $1; + $$->comp_op_ = $2; + $$->predicate_ = $3; + } + |bool_pri comp_op all_subquery { + $$ = new BoolPri(); + $$->case_idx_ = CASE3; + + $$->bool_pri_ = $1; + $$->comp_op_ = $2; + $$->all_subquery_ = $3; + } + |predicate { + $$ = new BoolPri(); + $$->case_idx_ = CASE4; + + $$->predicate_ = $1; + } + ; + +predicate: + bit_expr in_subquery { + $$ = new Predicate(); + $$->case_idx_ = CASE0; + + $$->bit_expr_1_ = $1; + $$->in_subquery_ = $2; + } + |bit_expr IN OP_LP expr OP_RP { + $$ = new Predicate(); + $$->case_idx_ = CASE1; + + $$->bit_expr_1_ = $1; + $$->expr_ = $4; + } + |bit_expr IN OP_LP expr OP_COMMA expr_list OP_RP { + $$ = new Predicate(); + $$->case_idx_ = CASE2; + + $$->bit_expr_1_ = $1; + $$->expr_ = $4; + $$->expr_list_ = $6; + } + |bit_expr NOT IN OP_LP expr OP_RP { + $$ = new Predicate(); + $$->case_idx_ = CASE3; + + $$->bit_expr_1_ = $1; + $$->expr_ = $5; + } + |bit_expr NOT IN OP_LP expr OP_COMMA expr_list OP_RP { + $$ = new Predicate(); + $$->case_idx_ = CASE4; + + $$->bit_expr_1_ = $1; + $$->expr_ = $5; + $$->expr_list_ = $7; + } + |bit_expr BETWEEN bit_expr AND predicate { + $$ = new Predicate(); + $$->case_idx_ = CASE5; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + $$->predicate_ = $5; + } + |bit_expr NOT BETWEEN bit_expr AND predicate { + $$ = new Predicate(); + $$->case_idx_ = CASE6; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $4; + $$->predicate_ = $6; + } + |bit_expr SOUNDS LIKE bit_expr { + $$ = new Predicate(); + $$->case_idx_ = CASE7; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $4; + } + |bit_expr LIKE simple_expr { + $$ = new Predicate(); + $$->case_idx_ = CASE8; + + $$->bit_expr_1_ = $1; + $$->simple_expr_ = $3; + } + |bit_expr NOT LIKE simple_expr { + $$ = new Predicate(); + $$->case_idx_ = CASE9; + + $$->bit_expr_1_ = $1; + $$->simple_expr_ = $4; + } + |bit_expr REGEXP bit_expr { + $$ = new Predicate(); + $$->case_idx_ = CASE10; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr NOT REGEXP bit_expr { + $$ = new Predicate(); + $$->case_idx_ = CASE11; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $4; + } + |bit_expr { + $$ = new Predicate(); + $$->case_idx_ = CASE12; + + $$->bit_expr_1_ = $1; + } + ; + +bit_expr: + bit_expr OP_OR bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE0; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_AND bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE1; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_SHL bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE2; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_SHR bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE3; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_ADD bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE4; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_SUB bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE5; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_MUL bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE6; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_DIVIDE bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE7; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_MOD bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE8; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |bit_expr OP_XOR bit_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE9; + + $$->bit_expr_1_ = $1; + $$->bit_expr_2_ = $3; + } + |simple_expr { + $$ = new BitExpr(); + $$->case_idx_ = CASE10; + + $$->simple_expr_ = $1; + } + ; + +simple_expr: + columnref { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE0; + + $$->columnref_ = $1; + } + |literal { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE1; + + $$->literal_ = $1; + } + |iconst { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE2; + + $$->iconst_ = $1; + } + |fconst { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE3; + + $$->fconst_ = $1; + } + |sconst { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE4; + + $$->sconst_ = $1; + } + |OP_ADD simple_expr %prec UMINUS { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE5; + + $$->simple_expr_ = $2; + } + |OP_SUB simple_expr %prec UMINUS { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE6; + + $$->simple_expr_ = $2; + } + |OP_NOT simple_expr %prec UMINUS { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE7; + + $$->simple_expr_ = $2; + } + |subquery { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE8; + + $$->subquery_ = $1; + } + |EXISTS subquery { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE9; + + $$->subquery_ = $2; + } + |type_cast { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE10; + + $$->type_cast_ = $1; + } + |case_expr { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE11; + + $$->case_expr_ = $1; + } + |DEFAULT OP_LP columnref OP_RP { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE12; + + $$->columnref_ = $3; + } + |function { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE13; + + $$->function_ = $1; + } + |OP_LP expr OP_RP { + $$ = new SimpleExpr(); + $$->case_idx_ = CASE14; + + $$->expr_ = $2; + } + ; + +function: + control_function { + $$ = new Function(); + $$->case_idx_ = CASE0; + + $$->control_function_ = $1; + } + |math_function { + $$ = new Function(); + $$->case_idx_ = CASE1; + + $$->math_function_ = $1; + } + |string_function { + $$ = new Function(); + $$->case_idx_ = CASE2; + + $$->string_function_ = $1; + } + |aggregate_function { + $$ = new Function(); + $$->case_idx_ = CASE3; + + $$->aggregate_function_ = $1; + } + |window_function { + $$ = new Function(); + $$->case_idx_ = CASE4; + + $$->window_function_ = $1; + } + ; + +string_function: + ASCII OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE0; + + $$->expr_1_ = $3; + } + |BIN OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE1; + + $$->expr_1_ = $3; + } + |BIT_LENGTH OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE2; + + $$->expr_1_ = $3; + } + |CHAR_LENGTH OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE3; + + $$->expr_1_ = $3; + } + |LENGTH OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE4; + + $$->expr_1_ = $3; + } + |LOWER OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE5; + + $$->expr_1_ = $3; + } + |LTRIM OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE6; + + $$->expr_1_ = $3; + } + |OCT OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE7; + + $$->expr_1_ = $3; + } + |ORD OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE8; + + $$->expr_1_ = $3; + } + |QUOTE OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE9; + + $$->expr_1_ = $3; + } + |REVERSE OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE10; + + $$->expr_1_ = $3; + } + |RTRIM OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE11; + + $$->expr_1_ = $3; + } + |SPACE OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE12; + + $$->expr_1_ = $3; + } + |TRIM OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE13; + + $$->expr_1_ = $3; + } + |TRIM OP_LP LEADING FROM expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE14; + + $$->expr_1_ = $5; + } + |TRIM OP_LP TRAILING FROM expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE15; + + $$->expr_1_ = $5; + } + |UNHEX OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE16; + + $$->expr_1_ = $3; + } + |UPPER OP_LP expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE17; + + $$->expr_1_ = $3; + } + |FIND_IN_SET OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE18; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |INSTR OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE19; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |LEFT OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE20; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |LOCATE OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE21; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |REPEAT OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE22; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |RIGHT OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE23; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |SUBSTRING OP_LP expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE24; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |TRIM OP_LP LEADING expr FROM expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE25; + + $$->expr_1_ = $4; + $$->expr_2_ = $6; + } + |TRIM OP_LP TRAILING expr FROM expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE26; + + $$->expr_1_ = $4; + $$->expr_2_ = $6; + } + |TRIM OP_LP expr FROM expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE27; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |EXPORT_SET OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE28; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |LOCATE OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE29; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |LPAD OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE30; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |REPLACE OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE31; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |RPAD OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE32; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |SUBSTRING OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE33; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |SUBSTRING_INDEX OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE34; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |EXPORT_SET OP_LP expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE35; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + $$->expr_4_ = $9; + } + |INSERT OP_LP expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE36; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + $$->expr_4_ = $9; + } + |EXPORT_SET OP_LP expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE37; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + $$->expr_4_ = $9; + $$->expr_5_ = $11; + } + |CHAR OP_LP expr_list OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE38; + + $$->expr_list_ = $3; + } + |CONCAT OP_LP expr_list OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE39; + + $$->expr_list_ = $3; + } + |CONCAT_WS OP_LP expr OP_COMMA expr_list OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE40; + + $$->expr_1_ = $3; + $$->expr_list_ = $5; + } + |ELT OP_LP expr OP_COMMA expr_list OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE41; + + $$->expr_1_ = $3; + $$->expr_list_ = $5; + } + |FIELD OP_LP expr OP_COMMA expr_list OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE42; + + $$->expr_1_ = $3; + $$->expr_list_ = $5; + } + |MAKE_SET OP_LP expr OP_COMMA expr_list OP_RP { + $$ = new StringFunction(); + $$->case_idx_ = CASE43; + + $$->expr_1_ = $3; + $$->expr_list_ = $5; + } + ; + +math_function: + PI OP_LP OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE0; + } + |RAND OP_LP OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE1; + } + |ABS OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE2; + + $$->expr_1_ = $3; + } + |ACOS OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE3; + + $$->expr_1_ = $3; + } + |ASIN OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE4; + + $$->expr_1_ = $3; + } + |ATAN OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE5; + + $$->expr_1_ = $3; + } + |CEILING OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE6; + + $$->expr_1_ = $3; + } + |COS OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE7; + + $$->expr_1_ = $3; + } + |COT OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE8; + + $$->expr_1_ = $3; + } + |DEGREES OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE9; + + $$->expr_1_ = $3; + } + |EXP OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE10; + + $$->expr_1_ = $3; + } + |FLOOR OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE11; + + $$->expr_1_ = $3; + } + |HEX OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE12; + + $$->expr_1_ = $3; + } + |LN OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE13; + + $$->expr_1_ = $3; + } + |RADIANS OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE14; + + $$->expr_1_ = $3; + } + |RAND OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE15; + + $$->expr_1_ = $3; + } + |ROUND OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE16; + + $$->expr_1_ = $3; + } + |SIGN OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE17; + + $$->expr_1_ = $3; + } + |SIN OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE18; + + $$->expr_1_ = $3; + } + |SQRT OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE19; + + $$->expr_1_ = $3; + } + |TAN OP_LP expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE20; + + $$->expr_1_ = $3; + } + |ATAN OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE21; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |FORMAT OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE22; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |LOG OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE23; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |MOD OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE24; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |POW OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE25; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |ROUND OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE26; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |TRUNCATE OP_LP expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE27; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |CONV OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new MathFunction(); + $$->case_idx_ = CASE28; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + ; + +window_function: + ROW_NUMBER OP_LP OP_RP windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE0; + + $$->windowing_clause_ = $4; + } + |RANK OP_LP OP_RP windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE1; + + $$->windowing_clause_ = $4; + } + |DENSE_RANK OP_LP OP_RP windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE2; + + $$->windowing_clause_ = $4; + } + |CUME_DIST OP_LP OP_RP windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE3; + + $$->windowing_clause_ = $4; + } + |PERCENT_RANK OP_LP OP_RP windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE4; + + $$->windowing_clause_ = $4; + } + |NTILE OP_LP iconst OP_RP windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE5; + + $$->iconst_ = $3; + $$->windowing_clause_ = $5; + } + |LEAD OP_LP expr opt_lead_lag_info OP_RP opt_null_treatment windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE6; + + $$->expr_ = $3; + $$->opt_lead_lag_info_ = $4; + $$->opt_null_treatment_ = $6; + $$->windowing_clause_ = $7; + } + |LAG OP_LP expr opt_lead_lag_info OP_RP opt_null_treatment windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE7; + + $$->expr_ = $3; + $$->opt_lead_lag_info_ = $4; + $$->opt_null_treatment_ = $6; + $$->windowing_clause_ = $7; + } + |FIRST_VALUE OP_LP expr OP_RP opt_null_treatment windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE8; + + $$->expr_ = $3; + $$->opt_null_treatment_ = $5; + $$->windowing_clause_ = $6; + } + |LAST_VALUE OP_LP expr OP_RP opt_null_treatment windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE9; + + $$->expr_ = $3; + $$->opt_null_treatment_ = $5; + $$->windowing_clause_ = $6; + } + |NTH_VALUE OP_LP expr OP_COMMA iconst OP_RP opt_from_first_last opt_null_treatment windowing_clause { + $$ = new WindowFunction(); + $$->case_idx_ = CASE10; + + $$->expr_ = $3; + $$->iconst_ = $5; + $$->opt_from_first_last_ = $7; + $$->opt_null_treatment_ = $8; + $$->windowing_clause_ = $9; + } + ; + +opt_null_treatment: + { + $$ = new OptNullTreatment(); + $$->case_idx_ = CASE0; + } + |RESPECT NULLS { + $$ = new OptNullTreatment(); + $$->case_idx_ = CASE1; + } + |IGNORE NULLS { + $$ = new OptNullTreatment(); + $$->case_idx_ = CASE2; + } + ; + +opt_from_first_last: + { + $$ = new OptFromFirstLast(); + $$->case_idx_ = CASE0; + } + |FROM FIRST { + $$ = new OptFromFirstLast(); + $$->case_idx_ = CASE1; + } + |FROM LAST { + $$ = new OptFromFirstLast(); + $$->case_idx_ = CASE2; + } + ; + +opt_lead_lag_info: + { + $$ = new OptLeadLagInfo(); + $$->case_idx_ = CASE0; + } + |lead_lag_info { + $$ = new OptLeadLagInfo(); + $$->case_idx_ = CASE1; + + $$->lead_lag_info_ = $1; + } + ; + +lead_lag_info: + OP_COMMA iconst { + $$ = new LeadLagInfo(); + $$->case_idx_ = CASE0; + + $$->iconst_ = $2; + } + |OP_COMMA iconst OP_COMMA expr { + $$ = new LeadLagInfo(); + $$->case_idx_ = CASE1; + + $$->iconst_ = $2; + $$->expr_ = $4; + } + ; + +aggregate_function: + AVG OP_LP opt_distinct expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE0; + + $$->opt_distinct_ = $3; + $$->expr_ = $4; + $$->opt_windowing_clause_ = $6; + } + |BIT_AND OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE1; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |BIT_OR OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE2; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |BIT_XOR OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE3; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |COUNT OP_LP OP_MUL OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE4; + + $$->opt_windowing_clause_ = $5; + } + |COUNT OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE5; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |COUNT OP_LP DISTINCT expr_list OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE6; + + $$->expr_list_ = $4; + $$->opt_windowing_clause_ = $6; + } + |MIN OP_LP opt_distinct expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE7; + + $$->opt_distinct_ = $3; + $$->expr_ = $4; + $$->opt_windowing_clause_ = $6; + } + |MAX OP_LP opt_distinct expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE8; + + $$->opt_distinct_ = $3; + $$->expr_ = $4; + $$->opt_windowing_clause_ = $6; + } + |SUM OP_LP opt_distinct expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE9; + + $$->opt_distinct_ = $3; + $$->expr_ = $4; + $$->opt_windowing_clause_ = $6; + } + |STD OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE10; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |STDDEV_SAMP OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE11; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |VARIANCE OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE12; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |VAR_SAMP OP_LP expr OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE13; + + $$->expr_ = $3; + $$->opt_windowing_clause_ = $5; + } + |GROUP_CONCAT OP_LP opt_distinct expr_list opt_order_clause opt_gconcat_separator OP_RP opt_windowing_clause { + $$ = new AggregateFunction(); + $$->case_idx_ = CASE14; + + $$->opt_distinct_ = $3; + $$->expr_list_ = $4; + $$->opt_order_clause_ = $5; + $$->opt_gconcat_separator_ = $6; + $$->opt_windowing_clause_ = $8; + } + ; + +opt_gconcat_separator: + { + $$ = new OptGconcatSeparator(); + $$->case_idx_ = CASE0; + } + |SEPARATOR sconst { + $$ = new OptGconcatSeparator(); + $$->case_idx_ = CASE1; + + $$->sconst_ = $2; + } + ; + +opt_distinct: + { + $$ = new OptDistinct(); + $$->case_idx_ = CASE0; + } + |DISTINCT { + $$ = new OptDistinct(); + $$->case_idx_ = CASE1; + } + ; + +opt_windowing_clause: + { + $$ = new OptWindowingClause(); + $$->case_idx_ = CASE0; + } + |windowing_clause { + $$ = new OptWindowingClause(); + $$->case_idx_ = CASE1; + + $$->windowing_clause_ = $1; + } + ; + +windowing_clause: + OVER window_name_or_spec { + $$ = new WindowingClause(); + $$->case_idx_ = CASE0; + + $$->window_name_or_spec_ = $2; + } + ; + +window_name_or_spec: + window_name { + $$ = new WindowNameOrSpec(); + $$->case_idx_ = CASE0; + + $$->window_name_ = $1; + } + |window_spec { + $$ = new WindowNameOrSpec(); + $$->case_idx_ = CASE1; + + $$->window_spec_ = $1; + } + ; + +control_function: + IF OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { + $$ = new ControlFunction(); + $$->case_idx_ = CASE0; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + $$->expr_3_ = $7; + } + |IFNULL OP_LP expr OP_COMMA expr OP_RP { + $$ = new ControlFunction(); + $$->case_idx_ = CASE1; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + |NULLIF OP_LP expr OP_COMMA expr OP_RP { + $$ = new ControlFunction(); + $$->case_idx_ = CASE2; + + $$->expr_1_ = $3; + $$->expr_2_ = $5; + } + ; + +case_expr: + CASE opt_expr when_clasue_list opt_else END { + $$ = new CaseExpr(); + $$->case_idx_ = CASE0; + + $$->opt_expr_ = $2; + $$->when_clasue_list_ = $3; + $$->opt_else_ = $4; + } + ; + +when_clasue_list: + when_list { + $$ = new WhenClasueList(); + $$->case_idx_ = CASE0; + + $$->when_list_ = $1; + } + |when_list when_clasue_list { + $$ = new WhenClasueList(); + $$->case_idx_ = CASE1; + + $$->when_list_ = $1; + $$->when_clasue_list_ = $2; + } + ; + +when_list: + WHEN expr THEN expr { + $$ = new WhenList(); + $$->case_idx_ = CASE0; + + $$->expr_1_ = $2; + $$->expr_2_ = $4; + } + ; + +opt_expr: + { + $$ = new OptExpr(); + $$->case_idx_ = CASE0; + } + |expr { + $$ = new OptExpr(); + $$->case_idx_ = CASE1; + + $$->expr_ = $1; + } + ; + +opt_else: + { + $$ = new OptElse(); + $$->case_idx_ = CASE0; + } + |ELSE expr { + $$ = new OptElse(); + $$->case_idx_ = CASE1; + + $$->expr_ = $2; + } + ; + +type_cast: + CAST OP_LP expr AS cast_type OP_RP { + $$ = new TypeCast(); + $$->case_idx_ = CASE0; + + $$->expr_ = $3; + $$->cast_type_ = $5; + } + |CONVERT OP_LP expr OP_COMMA cast_type OP_RP { + $$ = new TypeCast(); + $$->case_idx_ = CASE1; + + $$->expr_ = $3; + $$->cast_type_ = $5; + } + ; + +cast_type: + BINARY opt_field_length { + $$ = new CastType(); + $$->case_idx_ = CASE0; + + $$->opt_field_length_ = $2; + } + |CHAR opt_field_length { + $$ = new CastType(); + $$->case_idx_ = CASE1; + + $$->opt_field_length_ = $2; + } + |NCHAR opt_field_length { + $$ = new CastType(); + $$->case_idx_ = CASE2; + + $$->opt_field_length_ = $2; + } + |SIGNED { + $$ = new CastType(); + $$->case_idx_ = CASE3; + } + |UNSIGNED { + $$ = new CastType(); + $$->case_idx_ = CASE4; + } + |DECIMAL float_options { + $$ = new CastType(); + $$->case_idx_ = CASE5; + + $$->float_options_ = $2; + } + |REAL { + $$ = new CastType(); + $$->case_idx_ = CASE6; + } + |FLOAT opt_field_length { + $$ = new CastType(); + $$->case_idx_ = CASE7; + + $$->opt_field_length_ = $2; + } + ; + +float_options: + { + $$ = new FloatOptions(); + $$->case_idx_ = CASE0; + } + |field_length { + $$ = new FloatOptions(); + $$->case_idx_ = CASE1; + + $$->field_length_ = $1; + } + |precision { + $$ = new FloatOptions(); + $$->case_idx_ = CASE2; + + $$->precision_ = $1; + } + ; + +precision: + OP_LP iconst OP_COMMA iconst OP_RP { + $$ = new Precision(); + $$->case_idx_ = CASE0; + + $$->iconst_1_ = $2; + $$->iconst_2_ = $4; + } + ; + +opt_field_length: + { + $$ = new OptFieldLength(); + $$->case_idx_ = CASE0; + } + |field_length { + $$ = new OptFieldLength(); + $$->case_idx_ = CASE1; + + $$->field_length_ = $1; + } + ; + +field_length: + OP_LP iconst OP_RP { + $$ = new FieldLength(); + $$->case_idx_ = CASE0; + + $$->iconst_ = $2; + } + ; + +literal: + NULL { + $$ = new Literal(); + $$->case_idx_ = CASE0; + } + |FALSE { + $$ = new Literal(); + $$->case_idx_ = CASE1; + } + |TRUE { + $$ = new Literal(); + $$->case_idx_ = CASE2; + } + ; + +columnref: + column_name { + $$ = new Columnref(); + $$->case_idx_ = CASE0; + + $$->column_name_ = $1; + } + |table_name OP_DOT column_name { + $$ = new Columnref(); + $$->case_idx_ = CASE1; + + $$->table_name_ = $1; + $$->column_name_ = $3; + } + ; + +comp_op: + OP_EQUAL { + $$ = new CompOp(); + $$->case_idx_ = CASE0; + } + |OP_GREATEREQ { + $$ = new CompOp(); + $$->case_idx_ = CASE1; + } + |OP_GREATERTHAN { + $$ = new CompOp(); + $$->case_idx_ = CASE2; + } + |OP_LESSEQ { + $$ = new CompOp(); + $$->case_idx_ = CASE3; + } + |OP_LESSTHAN { + $$ = new CompOp(); + $$->case_idx_ = CASE4; + } + |OP_NOTEQUAL { + $$ = new CompOp(); + $$->case_idx_ = CASE5; + } + ; + +all_subquery: + ALL subquery { + $$ = new AllSubquery(); + $$->case_idx_ = CASE0; + + $$->subquery_ = $2; + } + |ANY subquery { + $$ = new AllSubquery(); + $$->case_idx_ = CASE1; + + $$->subquery_ = $2; + } + |SOME subquery { + $$ = new AllSubquery(); + $$->case_idx_ = CASE2; + + $$->subquery_ = $2; + } + ; + +in_subquery: + IN subquery { + $$ = new InSubquery(); + $$->case_idx_ = CASE0; + + $$->subquery_ = $2; + } + |NOT IN subquery { + $$ = new InSubquery(); + $$->case_idx_ = CASE1; + + $$->subquery_ = $3; + } + ; + +expr_list: + expr { + $$ = new ExprList(); + $$->case_idx_ = CASE0; + + $$->expr_ = $1; + } + |expr OP_COMMA expr_list { + $$ = new ExprList(); + $$->case_idx_ = CASE1; + + $$->expr_ = $1; + $$->expr_list_ = $3; + } + ; + +iconst: + ICONST { + $$ = new Iconst(); + $$->case_idx_ = CASE0; + + $$->long_val_ = $1; + } + ; + +fconst: + FCONST { + $$ = new Fconst(); + $$->case_idx_ = CASE0; + + $$->float_val_ = $1; + } + ; + +sconst: + SCONST { + $$ = new Sconst(); + $$->case_idx_ = CASE0; + + $$->str_val_ = $1; + free($1); + } + ; + +ident: + IDENT { + $$ = new Ident(); + $$->case_idx_ = CASE0; + + $$->str_val_ = $1; + free($1); + } + ; + +alias: + ident { + $$ = new Alias(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +column_name: + ident { + $$ = new ColumnName(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +window_name: + ident { + $$ = new WindowName(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +table_name: + ident { + $$ = new TableName(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +constraint_name: + ident { + $$ = new ConstraintName(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +index_name: + ident { + $$ = new IndexName(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +view_name: + ident { + $$ = new ViewName(); + $$->case_idx_ = CASE0; + + $$->ident_ = $1; + } + ; + +%% + diff --git a/parser/flex.l b/parser/flex.l new file mode 100755 index 0000000..f81f634 --- /dev/null +++ b/parser/flex.l @@ -0,0 +1,339 @@ +%{ +#include "bison_parser.h" +#include +#include +#include +#include +#define TOKEN(name) { return SQL_##name; } +static thread_local std::stringstream strbuf; +%} + +%{ + +#define YYLTYPE_IS_DECLARED 1 + +#define YY_USER_ACTION \ + yylloc->first_line = yylloc->last_line; \ + yylloc->first_column = yylloc->last_column; \ + for(int i = 0; yytext[i] != '\0'; i++) { \ + if(yytext[i] == '\n') { \ + yylloc->last_line++; \ + yylloc->last_column = 0; \ + } \ + else { \ + yylloc->last_column++; \ + } \ + } +%} + +%option reentrant +%option bison-bridge +%option never-interactive +%option batch +%option noyywrap +%option nounput +%option warn +%option case-insensitive +%option bison-locations +%option header-file="flex_lexer.h" +%option outfile="flex_lexer.cpp" +%option prefix="ff_" +%s COMMENT +%x singlequotedstring + +%% + +";" TOKEN(OP_SEMI) +FROM TOKEN(FROM) +DELETE TOKEN(DELETE) +QUICK TOKEN(QUICK) +LOW_PRIORITY TOKEN(LOW_PRIORITY) +IGNORE TOKEN(IGNORE) +ALTER TOKEN(ALTER) +TABLE TOKEN(TABLE) +"," TOKEN(OP_COMMA) +ADD TOKEN(ADD) +COLUMN TOKEN(COLUMN) +")" TOKEN(OP_RP) +"(" TOKEN(OP_LP) +CHANGE TOKEN(CHANGE) +MODIFY TOKEN(MODIFY) +DROP TOKEN(DROP) +FOREIGN TOKEN(FOREIGN) +KEY TOKEN(KEY) +PRIMARY TOKEN(PRIMARY) +INDEX TOKEN(INDEX) +CHECK TOKEN(CHECK) +CONSTRAINT TOKEN(CONSTRAINT) +SET TOKEN(SET) +DEFAULT TOKEN(DEFAULT) +RENAME TOKEN(RENAME) +TO TOKEN(TO) +AFTER TOKEN(AFTER) +FIRST TOKEN(FIRST) +ON TOKEN(ON) +IF TOKEN(IF) +EXISTS TOKEN(EXISTS) +VIEW TOKEN(VIEW) +UPDATE TOKEN(UPDATE) +LIMIT TOKEN(LIMIT) +INTO TOKEN(INTO) +INSERT TOKEN(INSERT) +VALUES TOKEN(VALUES) +AS TOKEN(AS) +DUPLICATE TOKEN(DUPLICATE) +"=" TOKEN(OP_EQUAL) +DELAYED TOKEN(DELAYED) +HIGH_PRIORITY TOKEN(HIGH_PRIORITY) +CREATE TOKEN(CREATE) +UNIQUE TOKEN(UNIQUE) +OR TOKEN(OR) +REPLACE TOKEN(REPLACE) +ALGORITHM TOKEN(ALGORITHM) +UNDEFINED TOKEN(UNDEFINED) +MERGE TOKEN(MERGE) +TEMPTABLE TOKEN(TEMPTABLE) +TEMPORARY TOKEN(TEMPORARY) +NOT TOKEN(NOT) +CHAR TOKEN(CHAR) +BINARY TOKEN(BINARY) +VARCHAR TOKEN(VARCHAR) +VARBINARY TOKEN(VARBINARY) +LONG TOKEN(LONG) +TINYBLOB TOKEN(TINYBLOB) +MEDIUMBLOB TOKEN(MEDIUMBLOB) +LONGBLOB TOKEN(LONGBLOB) +BLOB TOKEN(BLOB) +TINYTEXT TOKEN(TINYTEXT) +MEDIUMTEXT TOKEN(MEDIUMTEXT) +LONGTEXT TOKEN(LONGTEXT) +TEXT TOKEN(TEXT) +BOOL TOKEN(BOOL) +BOOLEAN TOKEN(BOOLEAN) +FLOAT TOKEN(FLOAT) +DECIMAL TOKEN(DECIMAL) +NUMERIC TOKEN(NUMERIC) +FIXED TOKEN(FIXED) +REAL TOKEN(REAL) +DOUBLE TOKEN(DOUBLE) +INT TOKEN(INT) +TINYINT TOKEN(TINYINT) +SMALLINT TOKEN(SMALLINT) +MEDIUMINT TOKEN(MEDIUMINT) +BIGINT TOKEN(BIGINT) +SIGNED TOKEN(SIGNED) +UNSIGNED TOKEN(UNSIGNED) +ZEROFILL TOKEN(ZEROFILL) +NULL TOKEN(NULL) +VISIBLE TOKEN(VISIBLE) +INVISIBLE TOKEN(INVISIBLE) +REFERENCES TOKEN(REFERENCES) +CASCADE TOKEN(CASCADE) +NO TOKEN(NO) +ACTION TOKEN(ACTION) +UNION TOKEN(UNION) +EXCEPT TOKEN(EXCEPT) +INTERSECT TOKEN(INTERSECT) +SELECT TOKEN(SELECT) +WINDOW TOKEN(WINDOW) +PARTITION TOKEN(PARTITION) +BY TOKEN(BY) +ORDER TOKEN(ORDER) +ASC TOKEN(ASC) +DESC TOKEN(DESC) +ROWS TOKEN(ROWS) +RANGE TOKEN(RANGE) +UNBOUNDED TOKEN(UNBOUNDED) +PRECEDING TOKEN(PRECEDING) +CURRENT TOKEN(CURRENT) +ROW TOKEN(ROW) +AND TOKEN(AND) +BETWEEN TOKEN(BETWEEN) +FOLLOWING TOKEN(FOLLOWING) +HAVING TOKEN(HAVING) +GROUP TOKEN(GROUP) +WITH TOKEN(WITH) +ROLLUP TOKEN(ROLLUP) +WHERE TOKEN(WHERE) +LATERAL TOKEN(LATERAL) +USING TOKEN(USING) +JOIN TOKEN(JOIN) +INNER TOKEN(INNER) +CROSS TOKEN(CROSS) +STRAIGHT_JOIN TOKEN(STRAIGHT_JOIN) +NATURAL TOKEN(NATURAL) +RIGHT TOKEN(RIGHT) +LEFT TOKEN(LEFT) +OUTER TOKEN(OUTER) +"*" TOKEN(OP_MUL) +"." TOKEN(OP_DOT) +SQL_NO_CACHE TOKEN(SQL_NO_CACHE) +DISTINCT TOKEN(DISTINCT) +SQL_SMALL_RESULT TOKEN(SQL_SMALL_RESULT) +SQL_BIG_RESULT TOKEN(SQL_BIG_RESULT) +SQL_BUFFER_RESULT TOKEN(SQL_BUFFER_RESULT) +SQL_CALC_FOUND_ROWS TOKEN(SQL_CALC_FOUND_ROWS) +ALL TOKEN(ALL) +RECURSIVE TOKEN(RECURSIVE) +XOR TOKEN(XOR) +IS TOKEN(IS) +TRUE TOKEN(TRUE) +FALSE TOKEN(FALSE) +UNKNOWN TOKEN(UNKNOWN) +IN TOKEN(IN) +SOUNDS TOKEN(SOUNDS) +LIKE TOKEN(LIKE) +REGEXP TOKEN(REGEXP) +"|" TOKEN(OP_OR) +"&" TOKEN(OP_AND) +"<<" TOKEN(OP_SHL) +">>" TOKEN(OP_SHR) +"+" TOKEN(OP_ADD) +"-" TOKEN(OP_SUB) +"/" TOKEN(OP_DIVIDE) +"%" TOKEN(OP_MOD) +"^" TOKEN(OP_XOR) +"~" TOKEN(OP_NOT) +ASCII TOKEN(ASCII) +BIN TOKEN(BIN) +BIT_LENGTH TOKEN(BIT_LENGTH) +CHAR_LENGTH TOKEN(CHAR_LENGTH) +LENGTH TOKEN(LENGTH) +LOWER TOKEN(LOWER) +LTRIM TOKEN(LTRIM) +OCT TOKEN(OCT) +ORD TOKEN(ORD) +QUOTE TOKEN(QUOTE) +REVERSE TOKEN(REVERSE) +RTRIM TOKEN(RTRIM) +SPACE TOKEN(SPACE) +TRIM TOKEN(TRIM) +LEADING TOKEN(LEADING) +TRAILING TOKEN(TRAILING) +UNHEX TOKEN(UNHEX) +UPPER TOKEN(UPPER) +FIND_IN_SET TOKEN(FIND_IN_SET) +INSTR TOKEN(INSTR) +LOCATE TOKEN(LOCATE) +REPEAT TOKEN(REPEAT) +SUBSTRING TOKEN(SUBSTRING) +EXPORT_SET TOKEN(EXPORT_SET) +LPAD TOKEN(LPAD) +RPAD TOKEN(RPAD) +SUBSTRING_INDEX TOKEN(SUBSTRING_INDEX) +CONCAT TOKEN(CONCAT) +CONCAT_WS TOKEN(CONCAT_WS) +ELT TOKEN(ELT) +FIELD TOKEN(FIELD) +MAKE_SET TOKEN(MAKE_SET) +PI TOKEN(PI) +RAND TOKEN(RAND) +ABS TOKEN(ABS) +ACOS TOKEN(ACOS) +ASIN TOKEN(ASIN) +ATAN TOKEN(ATAN) +CEILING TOKEN(CEILING) +COS TOKEN(COS) +COT TOKEN(COT) +DEGREES TOKEN(DEGREES) +EXP TOKEN(EXP) +FLOOR TOKEN(FLOOR) +HEX TOKEN(HEX) +LN TOKEN(LN) +RADIANS TOKEN(RADIANS) +ROUND TOKEN(ROUND) +SIGN TOKEN(SIGN) +SIN TOKEN(SIN) +SQRT TOKEN(SQRT) +TAN TOKEN(TAN) +FORMAT TOKEN(FORMAT) +LOG TOKEN(LOG) +MOD TOKEN(MOD) +POW TOKEN(POW) +TRUNCATE TOKEN(TRUNCATE) +CONV TOKEN(CONV) +ROW_NUMBER TOKEN(ROW_NUMBER) +RANK TOKEN(RANK) +DENSE_RANK TOKEN(DENSE_RANK) +CUME_DIST TOKEN(CUME_DIST) +PERCENT_RANK TOKEN(PERCENT_RANK) +NTILE TOKEN(NTILE) +LEAD TOKEN(LEAD) +LAG TOKEN(LAG) +FIRST_VALUE TOKEN(FIRST_VALUE) +LAST_VALUE TOKEN(LAST_VALUE) +NTH_VALUE TOKEN(NTH_VALUE) +RESPECT TOKEN(RESPECT) +NULLS TOKEN(NULLS) +LAST TOKEN(LAST) +AVG TOKEN(AVG) +BIT_AND TOKEN(BIT_AND) +BIT_OR TOKEN(BIT_OR) +BIT_XOR TOKEN(BIT_XOR) +COUNT TOKEN(COUNT) +MIN TOKEN(MIN) +MAX TOKEN(MAX) +SUM TOKEN(SUM) +STD TOKEN(STD) +STDDEV_SAMP TOKEN(STDDEV_SAMP) +VARIANCE TOKEN(VARIANCE) +VAR_SAMP TOKEN(VAR_SAMP) +GROUP_CONCAT TOKEN(GROUP_CONCAT) +SEPARATOR TOKEN(SEPARATOR) +OVER TOKEN(OVER) +IFNULL TOKEN(IFNULL) +NULLIF TOKEN(NULLIF) +END TOKEN(END) +CASE TOKEN(CASE) +THEN TOKEN(THEN) +WHEN TOKEN(WHEN) +ELSE TOKEN(ELSE) +CAST TOKEN(CAST) +CONVERT TOKEN(CONVERT) +NCHAR TOKEN(NCHAR) +">=" TOKEN(OP_GREATEREQ) +">" TOKEN(OP_GREATERTHAN) +"<=" TOKEN(OP_LESSEQ) +"<" TOKEN(OP_LESSTHAN) +"!=" TOKEN(OP_NOTEQUAL) +ANY TOKEN(ANY) +SOME TOKEN(SOME) + +-?[0-9]+"."[0-9]* | +"."[0-9]* { + yylval->double_value = atof(yytext); + return SQL_FCONST; +} + +-?[0-9]+ { + yylval->long_value = atol(yytext); + return SQL_ICONST; +} + +[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] { + +} + +[-][-].* { + +} + +\'[^\']*\' { + yylval->charp_value = strdup(yytext); + return SQL_SCONST; +} + +[A-Za-z$][A-Za-z0-9_]*[$]? { + yylval->charp_value = strdup(yytext); + return SQL_IDENT; +} + +[ \t\n]+ { + +} + +. { + return 0; +} + +%% diff --git a/parser/parser_typedef.h b/parser/parser_typedef.h new file mode 100755 index 0000000..ada28ec --- /dev/null +++ b/parser/parser_typedef.h @@ -0,0 +1,51 @@ +#ifndef __PARSER_TYPEDEF_H__ +#define __PARSER_TYPEDEF_H__ + +#include + + +#ifndef YYtypeDEF_YY_SCANNER_T +#define YYtypeDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + + +#define YYSTYPE FF_STYPE +#define YYLTYPE FF_LTYPE + + +struct FF_CUST_LTYPE { + int first_line; + int first_column; + int last_line; + int last_column; + + int total_column; + + // Length of the string in the SQL query string + int string_length; + + // Parameters. + // int param_id; + std::vector param_list; +}; + +#define FF_LTYPE FF_CUST_LTYPE +#define FF_LTYPE_IS_DECLARED 1 + +#define YY_USER_ACTION \ + yylloc->first_line = yylloc->last_line; \ + yylloc->first_column = yylloc->last_column; \ + for(int i = 0; yytext[i] != '\0'; i++) { \ + yylloc->total_column++; \ + yylloc->string_length++; \ + if(yytext[i] == '\n') { \ + yylloc->last_line++; \ + yylloc->last_column = 0; \ + } \ + else { \ + yylloc->last_column++; \ + } \ + } + +#endif \ No newline at end of file diff --git a/src/ast.cpp b/src/ast.cpp new file mode 100755 index 0000000..9bdb0c8 --- /dev/null +++ b/src/ast.cpp @@ -0,0 +1,5546 @@ +#include "../include/ast.h" +#include "../include/define.h" +#include + +using namespace std; + +//TRIM**SUBSTRING**BIT_AND**BIT_OR**BIT_XOR**COUNT**MIN**MAX**SUM**STD**STDDEV_SAMP**VARIANCE**VAR_SAMP**GROUP_CONCAT** + +const char* convertToTerminal[] = { + ";", + "FROM", + "DELETE", + "", + "QUICK", + "LOW_PRIORITY", + "IGNORE", + "ALTER TABLE", + ",", + "ADD COLUMN", + ")", + "ADD COLUMN (", + "ADD", + "CHANGE COLUMN", + "MODIFY COLUMN", + "DROP COLUMN", + "DROP FOREIGN KEY", + "DROP PRIMARY KEY", + "DROP INDEX", + "DROP CHECK", + "DROP CONSTRAINT", + "SET DEFAULT (", + "ALTER COLUMN", + "DROP DEFAULT", + "SET", + "ALTER INDEX", + "RENAME TO", + "TO", + "RENAME INDEX", + "RENAME COLUMN", + "AFTER", + "FIRST", + "ON", + "DROP TABLE", + "IF EXISTS", + "DROP VIEW", + "UPDATE", + "LIMIT", + "INTO", + "INSERT", + "(", + "VALUES", + ") VALUES", + "DEFAULT", + "AS", + "ON DUPLICATE KEY UPDATE", + "=", + "DELAYED", + "HIGH_PRIORITY", + "INDEX", + "CREATE", + "UNIQUE", + "VIEW", + "OR REPLACE", + "ALGORITHM = UNDEFINED", + "ALGORITHM = MERGE", + "ALGORITHM = TEMPTABLE", + "TABLE", + "TEMPORARY", + "IF NOT EXISTS", + "REPLACE", + "CHAR", + "BINARY", + "VARCHAR", + "VARBINARY", + "LONG VARBINARY", + "TINYBLOB", + "MEDIUMBLOB", + "LONGBLOB", + "BLOB", + "TINYTEXT", + "MEDIUMTEXT", + "LONGTEXT", + "TEXT", + "BOOL", + "BOOLEAN", + "FLOAT", + "DECIMAL", + "NUMERIC", + "FIXED", + "REAL", + "DOUBLE", + "INT", + "TINYINT", + "SMALLINT", + "MEDIUMINT", + "BIGINT", + "SIGNED", + "UNSIGNED", + "ZEROFILL", + "DEFAULT (", + "NOT NULL", + "VISIBLE", + "INVISIBLE", + "CONSTRAINT", + "CHECK (", + "FOREIGN KEY", + "REFERENCES", + "ON UPDATE", + "ON DELETE", + "CASCADE", + "SET NULL", + "NO ACTION", + "SET DEFAULT", + "PRIMARY KEY", + "UNION", + "EXCEPT", + "INTERSECT", + "SELECT", + "WINDOW", + "PARTITION BY", + "ORDER BY", + "ASC", + "DESC", + "ROWS", + "RANGE", + "UNBOUNDED PRECEDING", + "PRECEDING", + "CURRENT ROW", + "AND", + "BETWEEN", + "UNBOUNDED FOLLOWING", + "FOLLOWING", + "HAVING", + "GROUP BY", + "WITH ROLLUP", + "WHERE", + "LATERAL", + "USING (", + "JOIN", + "INNER JOIN", + "CROSS JOIN", + "STRAIGHT_JOIN", + "NATURAL", + "NATURAL RIGHT", + "NATURAL LEFT", + "INNER", + "OUTER", + "LEFT", + "RIGHT", + "*", + ". *", + "SQL_NO_CACHE", + "DISTINCT", + "SQL_SMALL_RESULT", + "SQL_BIG_RESULT", + "SQL_BUFFER_RESULT", + "SQL_CALC_FOUND_ROWS", + "ALL", + "WITH", + "WITH RECURSIVE", + "OR", + "XOR", + "NOT", + "IS TRUE", + "IS NOT TRUE", + "IS FALSE", + "IS NOT FALSE", + "IS UNKNOWN", + "IS NOT UNKNOWN", + "IS NULL", + "IS NOT NULL", + "IN (", + "NOT IN (", + "NOT BETWEEN", + "SOUNDS LIKE", + "LIKE", + "NOT LIKE", + "REGEXP", + "NOT REGEXP", + "|", + "&", + "<<", + ">>", + "+", + "-", + "/", + "%", + "^", + "~", + "EXISTS", + "ASCII (", + "BIN (", + "BIT_LENGTH (", + "CHAR_LENGTH (", + "LENGTH (", + "LOWER (", + "LTRIM (", + "OCT (", + "ORD (", + "QUOTE (", + "REVERSE (", + "RTRIM (", + "SPACE (", + "TRIM(", + "TRIM( LEADING FROM", + "TRIM( TRAILING FROM", + "UNHEX (", + "UPPER (", + "FIND_IN_SET (", + "INSTR (", + "LEFT (", + "LOCATE (", + "REPEAT (", + "RIGHT (", + "SUBSTRING(", + "TRIM( LEADING", + "TRIM( TRAILING", + "EXPORT_SET (", + "LPAD (", + "REPLACE (", + "RPAD (", + "SUBSTRING_INDEX (", + "INSERT (", + "CHAR (", + "CONCAT (", + "CONCAT_WS (", + "ELT (", + "FIELD (", + "MAKE_SET (", + "PI ( )", + "RAND ( )", + "ABS (", + "ACOS (", + "ASIN (", + "ATAN (", + "CEILING (", + "COS (", + "COT (", + "DEGREES (", + "EXP (", + "FLOOR (", + "HEX (", + "LN (", + "RADIANS (", + "RAND (", + "ROUND (", + "SIGN (", + "SIN (", + "SQRT (", + "TAN (", + "FORMAT (", + "LOG (", + "MOD (", + "POW (", + "TRUNCATE (", + "CONV (", + "ROW_NUMBER ( )", + "RANK ( )", + "DENSE_RANK ( )", + "CUME_DIST ( )", + "PERCENT_RANK ( )", + "NTILE (", + "LEAD (", + "LAG (", + "FIRST_VALUE (", + "LAST_VALUE (", + "NTH_VALUE (", + "RESPECT NULLS", + "IGNORE NULLS", + "FROM FIRST", + "FROM LAST", + "AVG (", + "BIT_AND(", + "BIT_OR(", + "BIT_XOR(", + "COUNT( * )", + "COUNT(", + "COUNT( DISTINCT", + "MIN(", + "MAX(", + "SUM(", + "STD(", + "STDDEV_SAMP(", + "VARIANCE(", + "VAR_SAMP(", + "GROUP_CONCAT(", + "SEPARATOR", + "OVER", + "IF (", + "IFNULL (", + "NULLIF (", + "END", + "CASE", + "THEN", + "WHEN", + "ELSE", + "CAST (", + "CONVERT (", + "NCHAR", + "NULL", + "FALSE", + "TRUE", + ".", + ">=", + ">", + "<=", + "<", + "!=", + "ANY", + "SOME", + "IN", + "NOT IN", + "ICONST", + "FCONST", + "SCONST", + "IDENT", +}; + +void deep_delete(IR * root){ + if (!root) + return; + + if(root->left_) deep_delete(root->left_); + if(root->right_) deep_delete(root->right_); + + if(root->op_) delete root->op_; + + delete root; +} + +IR* deep_copy(const IR* root) { + IR* left = NULL, * right = NULL, * copy_res; + + if (root == nullptr) return nullptr; + + if (root->left_) left = deep_copy(root->left_); + if (root->right_) right = deep_copy(root->right_); + + copy_res = new IR(root, left, right); + + return copy_res; +} + +string IR::to_string(){ + auto res = to_string_core(); + trim_string(res); + return res; +} + +string IR::to_string_core(){ + switch (type_) { + case kIconst: + return std::to_string(long_val_) + " "; + case kFconst: + return std::to_string(float_val_) + " "; + case kSconst: + return str_val_ + " "; + case kIdent: + return str_val_ + " "; + } + + string res; + + if (op_->prefix_ != tEmpty) + res += string(convertToTerminal[op_->prefix_]) + " "; + if (left_ != NULL) + res += left_->to_string_core(); + if (op_->middle_ != tEmpty) + res += string(convertToTerminal[op_->middle_]) + " "; + if (right_ != NULL) + res += right_->to_string_core(); + if (op_->suffix_ != tEmpty) + res += string(convertToTerminal[op_->suffix_]) + " "; + + return res; +} + +void IR::trim_string(string& res) { + char preChar = 0; + int count = 0; + + for (int i = 0; i < res.size(); i++) { + if ((res[i] == ' ') && (preChar == ';')) + res[i] = '\n'; + + preChar = res[i]; + } + + return; +} + +IR* ParseToplevel::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(stmtmulti_); + res = new IR(IRTYPE::kParseToplevel, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void ParseToplevel::deep_delete() { + SAFEDELETE(stmtmulti_); + delete this; +} + +IR* Stmtmulti::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(stmt_); + auto tmp2 = SAFETRANSLATE(stmtmulti_); + res = new IR(IRTYPE::kStmtmulti, OP3(TERMINAL::tEmpty, TERMINAL::tOpSemi, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(stmt_); + res = new IR(IRTYPE::kStmtmulti, OP3(TERMINAL::tEmpty, TERMINAL::tOpSemi, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Stmtmulti::deep_delete() { + SAFEDELETE(stmtmulti_); + SAFEDELETE(stmt_); + delete this; +} + +IR* Stmt::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(create_table_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(create_view_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(create_index_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(select_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(drop_index_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(drop_table_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(drop_view_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(delete_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(update_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(insert_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(alter_table_stmt_); + res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Stmt::deep_delete() { + SAFEDELETE(create_table_stmt_); + SAFEDELETE(create_view_stmt_); + SAFEDELETE(create_index_stmt_); + SAFEDELETE(select_stmt_); + SAFEDELETE(drop_index_stmt_); + SAFEDELETE(drop_table_stmt_); + SAFEDELETE(drop_view_stmt_); + SAFEDELETE(delete_stmt_); + SAFEDELETE(update_stmt_); + SAFEDELETE(insert_stmt_); + SAFEDELETE(alter_table_stmt_); + delete this; +} + +IR* DeleteStmt::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_with_clause_); + auto tmp2 = SAFETRANSLATE(opt_delete_options_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(opt_alias_); + auto tmp5 = SAFETRANSLATE(opt_where_clause_); + auto tmp6 = SAFETRANSLATE(opt_order_clause_); + auto tmp7 = SAFETRANSLATE(opt_simple_limit_); + auto tmp8 = new IR(IRTYPE::kDeleteStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp6, tmp7); + auto tmp9 = new IR(IRTYPE::kDeleteStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp8); + auto tmp10 = new IR(IRTYPE::kDeleteStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp9); + auto tmp11 = new IR(IRTYPE::kDeleteStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp10); + auto tmp12 = new IR(IRTYPE::kDeleteStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tFrom, TERMINAL::tEmpty), tmp2, tmp11); + res = new IR(IRTYPE::kDeleteStmt, OP3(TERMINAL::tEmpty, TERMINAL::tDelete, TERMINAL::tEmpty), tmp1, tmp12); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_with_clause_); + auto tmp2 = SAFETRANSLATE(opt_delete_options_); + auto tmp3 = SAFETRANSLATE(table_list_); + auto tmp4 = SAFETRANSLATE(table_reference_list_); + auto tmp5 = SAFETRANSLATE(opt_where_clause_); + auto tmp6 = new IR(IRTYPE::kDeleteStmtTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kDeleteStmtTmp7, OP3(TERMINAL::tEmpty, TERMINAL::tFrom, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kDeleteStmtTmp8, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kDeleteStmt, OP3(TERMINAL::tEmpty, TERMINAL::tDelete, TERMINAL::tEmpty), tmp1, tmp8); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void DeleteStmt::deep_delete() { + SAFEDELETE(opt_simple_limit_); + SAFEDELETE(opt_order_clause_); + SAFEDELETE(opt_where_clause_); + SAFEDELETE(opt_alias_); + SAFEDELETE(table_name_); + SAFEDELETE(opt_delete_options_); + SAFEDELETE(opt_with_clause_); + SAFEDELETE(table_reference_list_); + SAFEDELETE(table_list_); + delete this; +} + +IR* OptDeleteOptions::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(delete_options_); + res = new IR(IRTYPE::kOptDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptDeleteOptions::deep_delete() { + SAFEDELETE(delete_options_); + delete this; +} + +IR* DeleteOptions::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(delete_option_); + res = new IR(IRTYPE::kDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(delete_option_); + auto tmp2 = SAFETRANSLATE(delete_options_); + res = new IR(IRTYPE::kDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void DeleteOptions::deep_delete() { + SAFEDELETE(delete_option_); + SAFEDELETE(delete_options_); + delete this; +} + +IR* DeleteOption::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kDeleteOption, OP3(TERMINAL::tQuick, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kDeleteOption, OP3(TERMINAL::tLowPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kDeleteOption, OP3(TERMINAL::tIgnore, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void DeleteOption::deep_delete() { + delete this; +} + +IR* AlterTableStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(alter_list_); + res = new IR(IRTYPE::kAlterTableStmt, OP3(TERMINAL::tAlterTable, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void AlterTableStmt::deep_delete() { + SAFEDELETE(alter_list_); + SAFEDELETE(table_name_); + delete this; +} + +IR* AlterList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(alter_list_item_); + res = new IR(IRTYPE::kAlterList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(alter_list_item_); + auto tmp2 = SAFETRANSLATE(alter_list_); + res = new IR(IRTYPE::kAlterList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void AlterList::deep_delete() { + SAFEDELETE(alter_list_item_); + SAFEDELETE(alter_list_); + delete this; +} + +IR* AlterListItem::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(column_name_1_); + auto tmp2 = SAFETRANSLATE(field_def_); + auto tmp3 = SAFETRANSLATE(opt_place_); + auto tmp4 = new IR(IRTYPE::kAlterListItemTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAddColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_element_list_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAddColumnOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(table_constraint_def_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAdd, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(column_name_1_); + auto tmp2 = SAFETRANSLATE(column_name_2_); + auto tmp3 = SAFETRANSLATE(field_def_); + auto tmp4 = SAFETRANSLATE(opt_place_); + auto tmp5 = new IR(IRTYPE::kAlterListItemTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kAlterListItemTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tChangeColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(column_name_1_); + auto tmp2 = SAFETRANSLATE(field_def_); + auto tmp3 = SAFETRANSLATE(opt_place_); + auto tmp4 = new IR(IRTYPE::kAlterListItemTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tModifyColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(column_name_1_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(constraint_name_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropForeignKey, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(7) + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropPrimaryKey, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(index_name_1_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropIndex, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(constraint_name_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropCheck, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(constraint_name_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropConstraint, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(11) + auto tmp1 = SAFETRANSLATE(column_name_1_); + auto tmp2 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterColumn, TERMINAL::tSetDefaultOpLp, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(12) + auto tmp1 = SAFETRANSLATE(column_name_1_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterColumn, TERMINAL::tDropDefault, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(13) + auto tmp1 = SAFETRANSLATE(column_name_1_); + auto tmp2 = SAFETRANSLATE(visibility_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterColumn, TERMINAL::tSet, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(14) + auto tmp1 = SAFETRANSLATE(index_name_1_); + auto tmp2 = SAFETRANSLATE(visibility_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterIndex, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(15) + auto tmp1 = SAFETRANSLATE(table_name_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tRenameTo, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(16) + auto tmp1 = SAFETRANSLATE(index_name_1_); + auto tmp2 = SAFETRANSLATE(index_name_2_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tRenameIndex, TERMINAL::tTo, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(17) + auto tmp1 = SAFETRANSLATE(column_name_1_); + auto tmp2 = SAFETRANSLATE(column_name_2_); + res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tRenameColumn, TERMINAL::tTo, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void AlterListItem::deep_delete() { + SAFEDELETE(opt_place_); + SAFEDELETE(field_def_); + SAFEDELETE(column_name_1_); + SAFEDELETE(column_name_2_); + SAFEDELETE(table_element_list_); + SAFEDELETE(table_constraint_def_); + SAFEDELETE(constraint_name_); + SAFEDELETE(index_name_1_); + SAFEDELETE(index_name_2_); + SAFEDELETE(expr_root_); + SAFEDELETE(visibility_); + SAFEDELETE(table_name_); + delete this; +} + +IR* OptPlace::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptPlace, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_name_); + res = new IR(IRTYPE::kOptPlace, OP3(TERMINAL::tAfter, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOptPlace, OP3(TERMINAL::tFirst, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptPlace::deep_delete() { + SAFEDELETE(column_name_); + delete this; +} + +IR* DropIndexStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(index_name_); + auto tmp2 = SAFETRANSLATE(table_name_); + res = new IR(IRTYPE::kDropIndexStmt, OP3(TERMINAL::tDropIndex, TERMINAL::tOn, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void DropIndexStmt::deep_delete() { + SAFEDELETE(table_name_); + SAFEDELETE(index_name_); + delete this; +} + +IR* DropTableStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(if_exists_); + auto tmp2 = SAFETRANSLATE(table_list_); + res = new IR(IRTYPE::kDropTableStmt, OP3(TERMINAL::tDropTable, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void DropTableStmt::deep_delete() { + SAFEDELETE(table_list_); + SAFEDELETE(if_exists_); + delete this; +} + +IR* IfExists::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kIfExists, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kIfExists, OP3(TERMINAL::tIfExists, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void IfExists::deep_delete() { + delete this; +} + +IR* TableList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(table_name_); + res = new IR(IRTYPE::kTableList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(table_list_); + res = new IR(IRTYPE::kTableList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableList::deep_delete() { + SAFEDELETE(table_name_); + SAFEDELETE(table_list_); + delete this; +} + +IR* DropViewStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(if_exists_); + auto tmp2 = SAFETRANSLATE(table_list_); + res = new IR(IRTYPE::kDropViewStmt, OP3(TERMINAL::tDropView, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void DropViewStmt::deep_delete() { + SAFEDELETE(table_list_); + SAFEDELETE(if_exists_); + delete this; +} + +IR* UpdateStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_with_clause_); + auto tmp2 = SAFETRANSLATE(opt_low_priority_); + auto tmp3 = SAFETRANSLATE(opt_ignore_); + auto tmp4 = SAFETRANSLATE(table_reference_list_); + auto tmp5 = SAFETRANSLATE(update_list_); + auto tmp6 = SAFETRANSLATE(opt_where_clause_); + auto tmp7 = SAFETRANSLATE(opt_order_clause_); + auto tmp8 = SAFETRANSLATE(opt_simple_limit_); + auto tmp9 = new IR(IRTYPE::kUpdateStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp7, tmp8); + auto tmp10 = new IR(IRTYPE::kUpdateStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp6, tmp9); + auto tmp11 = new IR(IRTYPE::kUpdateStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp10); + auto tmp12 = new IR(IRTYPE::kUpdateStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tSet, TERMINAL::tEmpty), tmp4, tmp11); + auto tmp13 = new IR(IRTYPE::kUpdateStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp12); + auto tmp14 = new IR(IRTYPE::kUpdateStmtTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp13); + res = new IR(IRTYPE::kUpdateStmt, OP3(TERMINAL::tEmpty, TERMINAL::tUpdate, TERMINAL::tEmpty), tmp1, tmp14); + + TRANSLATEEND +} + +void UpdateStmt::deep_delete() { + SAFEDELETE(opt_simple_limit_); + SAFEDELETE(opt_order_clause_); + SAFEDELETE(opt_where_clause_); + SAFEDELETE(update_list_); + SAFEDELETE(table_reference_list_); + SAFEDELETE(opt_ignore_); + SAFEDELETE(opt_low_priority_); + SAFEDELETE(opt_with_clause_); + delete this; +} + +IR* OptSimpleLimit::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptSimpleLimit, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(iconst_); + res = new IR(IRTYPE::kOptSimpleLimit, OP3(TERMINAL::tLimit, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptSimpleLimit::deep_delete() { + SAFEDELETE(iconst_); + delete this; +} + +IR* OptWithClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptWithClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(with_clause_); + res = new IR(IRTYPE::kOptWithClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptWithClause::deep_delete() { + SAFEDELETE(with_clause_); + delete this; +} + +IR* OptLowPriority::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptLowPriority, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptLowPriority, OP3(TERMINAL::tLowPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptLowPriority::deep_delete() { + delete this; +} + +IR* InsertStmt::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(insert_lock_option_); + auto tmp2 = SAFETRANSLATE(opt_ignore_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(insert_from_constructor_); + auto tmp5 = SAFETRANSLATE(opt_values_reference_); + auto tmp6 = SAFETRANSLATE(opt_insert_update_list_); + auto tmp7 = new IR(IRTYPE::kInsertStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp6); + auto tmp8 = new IR(IRTYPE::kInsertStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp7); + auto tmp9 = new IR(IRTYPE::kInsertStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp8); + auto tmp10 = new IR(IRTYPE::kInsertStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tInto, TERMINAL::tEmpty), tmp2, tmp9); + res = new IR(IRTYPE::kInsertStmt, OP3(TERMINAL::tInsert, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp10); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(insert_lock_option_); + auto tmp2 = SAFETRANSLATE(opt_ignore_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(update_list_); + auto tmp5 = SAFETRANSLATE(opt_values_reference_); + auto tmp6 = SAFETRANSLATE(opt_insert_update_list_); + auto tmp7 = new IR(IRTYPE::kInsertStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp6); + auto tmp8 = new IR(IRTYPE::kInsertStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp7); + auto tmp9 = new IR(IRTYPE::kInsertStmtTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tSet, TERMINAL::tEmpty), tmp3, tmp8); + auto tmp10 = new IR(IRTYPE::kInsertStmtTmp7, OP3(TERMINAL::tEmpty, TERMINAL::tInto, TERMINAL::tEmpty), tmp2, tmp9); + res = new IR(IRTYPE::kInsertStmt, OP3(TERMINAL::tInsert, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp10); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(insert_lock_option_); + auto tmp2 = SAFETRANSLATE(opt_ignore_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(insert_query_expression_); + auto tmp5 = SAFETRANSLATE(opt_insert_update_list_); + auto tmp6 = new IR(IRTYPE::kInsertStmtTmp8, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kInsertStmtTmp9, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kInsertStmtTmp10, OP3(TERMINAL::tEmpty, TERMINAL::tInto, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kInsertStmt, OP3(TERMINAL::tInsert, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp8); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void InsertStmt::deep_delete() { + SAFEDELETE(opt_insert_update_list_); + SAFEDELETE(opt_values_reference_); + SAFEDELETE(insert_from_constructor_); + SAFEDELETE(table_name_); + SAFEDELETE(opt_ignore_); + SAFEDELETE(insert_lock_option_); + SAFEDELETE(update_list_); + SAFEDELETE(insert_query_expression_); + delete this; +} + +IR* InsertQueryExpression::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(query_expression_); + res = new IR(IRTYPE::kInsertQueryExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_list_); + auto tmp2 = SAFETRANSLATE(query_expression_); + res = new IR(IRTYPE::kInsertQueryExpression, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void InsertQueryExpression::deep_delete() { + SAFEDELETE(query_expression_); + SAFEDELETE(column_list_); + delete this; +} + +IR* InsertFromConstructor::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(values_list_); + res = new IR(IRTYPE::kInsertFromConstructor, OP3(TERMINAL::tValues, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_list_); + auto tmp2 = SAFETRANSLATE(values_list_); + res = new IR(IRTYPE::kInsertFromConstructor, OP3(TERMINAL::tOpLp, TERMINAL::tOpRpValues, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void InsertFromConstructor::deep_delete() { + SAFEDELETE(values_list_); + SAFEDELETE(column_list_); + delete this; +} + +IR* ValuesList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(row_value_); + res = new IR(IRTYPE::kValuesList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(row_value_); + auto tmp2 = SAFETRANSLATE(values_list_); + res = new IR(IRTYPE::kValuesList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ValuesList::deep_delete() { + SAFEDELETE(row_value_); + SAFEDELETE(values_list_); + delete this; +} + +IR* RowValue::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_values_); + res = new IR(IRTYPE::kRowValue, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void RowValue::deep_delete() { + SAFEDELETE(opt_values_); + delete this; +} + +IR* OptValues::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptValues, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(values_); + res = new IR(IRTYPE::kOptValues, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptValues::deep_delete() { + SAFEDELETE(values_); + delete this; +} + +IR* Values::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_or_default_); + res = new IR(IRTYPE::kValues, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_or_default_); + auto tmp2 = SAFETRANSLATE(values_); + res = new IR(IRTYPE::kValues, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Values::deep_delete() { + SAFEDELETE(expr_or_default_); + SAFEDELETE(values_); + delete this; +} + +IR* ExprOrDefault::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kExprOrDefault, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kExprOrDefault, OP3(TERMINAL::tDefault, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ExprOrDefault::deep_delete() { + SAFEDELETE(expr_root_); + delete this; +} + +IR* OptValuesReference::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptValuesReference, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(opt_column_list_); + res = new IR(IRTYPE::kOptValuesReference, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptValuesReference::deep_delete() { + SAFEDELETE(opt_column_list_); + SAFEDELETE(table_name_); + delete this; +} + +IR* OptInsertUpdateList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptInsertUpdateList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(update_list_); + res = new IR(IRTYPE::kOptInsertUpdateList, OP3(TERMINAL::tOnDuplicateKeyUpdate, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptInsertUpdateList::deep_delete() { + SAFEDELETE(update_list_); + delete this; +} + +IR* UpdateList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(update_elem_); + res = new IR(IRTYPE::kUpdateList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(update_elem_); + auto tmp2 = SAFETRANSLATE(update_list_); + res = new IR(IRTYPE::kUpdateList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void UpdateList::deep_delete() { + SAFEDELETE(update_elem_); + SAFEDELETE(update_list_); + delete this; +} + +IR* UpdateElem::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(columnref_); + auto tmp2 = SAFETRANSLATE(expr_or_default_); + res = new IR(IRTYPE::kUpdateElem, OP3(TERMINAL::tEmpty, TERMINAL::tOpEqual, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void UpdateElem::deep_delete() { + SAFEDELETE(expr_or_default_); + SAFEDELETE(columnref_); + delete this; +} + +IR* InsertLockOption::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tLowPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tDelayed, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tHighPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void InsertLockOption::deep_delete() { + delete this; +} + +IR* OptIgnore::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptIgnore, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptIgnore, OP3(TERMINAL::tIgnore, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptIgnore::deep_delete() { + delete this; +} + +IR* CreateIndexStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_unique_); + auto tmp2 = SAFETRANSLATE(index_name_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(key_list_with_expression_); + auto tmp5 = new IR(IRTYPE::kCreateIndexStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tOpRp), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kCreateIndexStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOn, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kCreateIndexStmt, OP3(TERMINAL::tCreate, TERMINAL::tIndex, TERMINAL::tEmpty), tmp1, tmp6); + + TRANSLATEEND +} + +void CreateIndexStmt::deep_delete() { + SAFEDELETE(key_list_with_expression_); + SAFEDELETE(table_name_); + SAFEDELETE(index_name_); + SAFEDELETE(opt_unique_); + delete this; +} + +IR* OptUnique::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptUnique, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptUnique, OP3(TERMINAL::tUnique, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptUnique::deep_delete() { + delete this; +} + +IR* CreateViewStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_or_replace_); + auto tmp2 = SAFETRANSLATE(opt_view_algorithm_); + auto tmp3 = SAFETRANSLATE(view_name_); + auto tmp4 = SAFETRANSLATE(opt_column_list_); + auto tmp5 = SAFETRANSLATE(query_expression_); + auto tmp6 = new IR(IRTYPE::kCreateViewStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kCreateViewStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kCreateViewStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tView, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kCreateViewStmt, OP3(TERMINAL::tCreate, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp8); + + TRANSLATEEND +} + +void CreateViewStmt::deep_delete() { + SAFEDELETE(query_expression_); + SAFEDELETE(opt_column_list_); + SAFEDELETE(view_name_); + SAFEDELETE(opt_view_algorithm_); + SAFEDELETE(opt_or_replace_); + delete this; +} + +IR* OptOrReplace::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptOrReplace, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptOrReplace, OP3(TERMINAL::tOrReplace, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptOrReplace::deep_delete() { + delete this; +} + +IR* OptViewAlgorithm::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tAlgorithmOpEqualUndefined, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tAlgorithmOpEqualMerge, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tAlgorithmOpEqualTemptable, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptViewAlgorithm::deep_delete() { + delete this; +} + +IR* CreateTableStmt::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_temporary_); + auto tmp2 = SAFETRANSLATE(opt_if_not_exists_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(table_element_list_); + auto tmp5 = SAFETRANSLATE(opt_duplicate_as_qe_); + auto tmp6 = new IR(IRTYPE::kCreateTableStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kCreateTableStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kCreateTableStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kCreateTableStmt, OP3(TERMINAL::tCreate, TERMINAL::tTable, TERMINAL::tEmpty), tmp1, tmp8); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_temporary_); + auto tmp2 = SAFETRANSLATE(opt_if_not_exists_); + auto tmp3 = SAFETRANSLATE(table_name_); + auto tmp4 = SAFETRANSLATE(duplicate_as_qe_); + auto tmp5 = new IR(IRTYPE::kCreateTableStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kCreateTableStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kCreateTableStmt, OP3(TERMINAL::tCreate, TERMINAL::tTable, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void CreateTableStmt::deep_delete() { + SAFEDELETE(opt_duplicate_as_qe_); + SAFEDELETE(table_element_list_); + SAFEDELETE(table_name_); + SAFEDELETE(opt_if_not_exists_); + SAFEDELETE(opt_temporary_); + SAFEDELETE(duplicate_as_qe_); + delete this; +} + +IR* OptTemporary::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptTemporary, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptTemporary, OP3(TERMINAL::tTemporary, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptTemporary::deep_delete() { + delete this; +} + +IR* OptIfNotExists::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptIfNotExists, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptIfNotExists, OP3(TERMINAL::tIfNotExists, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptIfNotExists::deep_delete() { + delete this; +} + +IR* OptDuplicateAsQe::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptDuplicateAsQe, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(duplicate_as_qe_); + res = new IR(IRTYPE::kOptDuplicateAsQe, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptDuplicateAsQe::deep_delete() { + SAFEDELETE(duplicate_as_qe_); + delete this; +} + +IR* DuplicateAsQe::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(duplicate_); + auto tmp2 = SAFETRANSLATE(query_expression_); + res = new IR(IRTYPE::kDuplicateAsQe, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(query_expression_); + res = new IR(IRTYPE::kDuplicateAsQe, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void DuplicateAsQe::deep_delete() { + SAFEDELETE(query_expression_); + SAFEDELETE(duplicate_); + delete this; +} + +IR* Duplicate::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kDuplicate, OP3(TERMINAL::tReplace, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kDuplicate, OP3(TERMINAL::tIgnore, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Duplicate::deep_delete() { + delete this; +} + +IR* TableElementList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(table_element_); + res = new IR(IRTYPE::kTableElementList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_element_); + auto tmp2 = SAFETRANSLATE(table_element_list_); + res = new IR(IRTYPE::kTableElementList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableElementList::deep_delete() { + SAFEDELETE(table_element_); + SAFEDELETE(table_element_list_); + delete this; +} + +IR* TableElement::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(column_def_); + res = new IR(IRTYPE::kTableElement, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_constraint_def_); + res = new IR(IRTYPE::kTableElement, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableElement::deep_delete() { + SAFEDELETE(column_def_); + SAFEDELETE(table_constraint_def_); + delete this; +} + +IR* ColumnDef::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(column_name_); + auto tmp2 = SAFETRANSLATE(field_def_); + res = new IR(IRTYPE::kColumnDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void ColumnDef::deep_delete() { + SAFEDELETE(field_def_); + SAFEDELETE(column_name_); + delete this; +} + +IR* FieldDef::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(data_type_); + auto tmp2 = SAFETRANSLATE(opt_column_attribute_list_); + res = new IR(IRTYPE::kFieldDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void FieldDef::deep_delete() { + SAFEDELETE(opt_column_attribute_list_); + SAFEDELETE(data_type_); + delete this; +} + +IR* DataType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(number_type_); + res = new IR(IRTYPE::kDataType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(bool_type_); + res = new IR(IRTYPE::kDataType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(string_type_); + res = new IR(IRTYPE::kDataType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void DataType::deep_delete() { + SAFEDELETE(number_type_); + SAFEDELETE(bool_type_); + SAFEDELETE(string_type_); + delete this; +} + +IR* StringType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tChar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tBinary, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(field_length_); + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tVarchar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(field_length_); + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tVarbinary, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tLongVarbinary, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(5) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tTinyblob, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(6) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tMediumblob, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(7) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tLongblob, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tBlob, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tTinytext, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(10) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tMediumtext, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(11) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tLongtext, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(12) + res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tText, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void StringType::deep_delete() { + SAFEDELETE(opt_field_length_); + SAFEDELETE(field_length_); + delete this; +} + +IR* BoolType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kBoolType, OP3(TERMINAL::tBool, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kBoolType, OP3(TERMINAL::tBoolean, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void BoolType::deep_delete() { + delete this; +} + +IR* NumberType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(int_type_); + auto tmp2 = SAFETRANSLATE(opt_field_options_); + res = new IR(IRTYPE::kNumberType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(real_type_); + auto tmp2 = SAFETRANSLATE(opt_precision_); + auto tmp3 = SAFETRANSLATE(opt_field_options_); + auto tmp4 = new IR(IRTYPE::kNumberTypeTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kNumberType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(numeric_type_); + auto tmp2 = SAFETRANSLATE(float_options_); + auto tmp3 = SAFETRANSLATE(opt_field_options_); + auto tmp4 = new IR(IRTYPE::kNumberTypeTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kNumberType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void NumberType::deep_delete() { + SAFEDELETE(opt_field_options_); + SAFEDELETE(int_type_); + SAFEDELETE(opt_precision_); + SAFEDELETE(real_type_); + SAFEDELETE(float_options_); + SAFEDELETE(numeric_type_); + delete this; +} + +IR* NumericType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tFloat, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tDecimal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tNumeric, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tFixed, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void NumericType::deep_delete() { + delete this; +} + +IR* RealType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kRealType, OP3(TERMINAL::tReal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kRealType, OP3(TERMINAL::tDouble, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void RealType::deep_delete() { + delete this; +} + +IR* OptPrecision::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptPrecision, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(precision_); + res = new IR(IRTYPE::kOptPrecision, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptPrecision::deep_delete() { + SAFEDELETE(precision_); + delete this; +} + +IR* IntType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tInt, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tTinyint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tSmallint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tMediumint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(4) + res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tBigint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void IntType::deep_delete() { + delete this; +} + +IR* OptFieldOptions::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptFieldOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(field_option_list_); + res = new IR(IRTYPE::kOptFieldOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptFieldOptions::deep_delete() { + SAFEDELETE(field_option_list_); + delete this; +} + +IR* FieldOptionList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(field_option_); + res = new IR(IRTYPE::kFieldOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(field_option_); + auto tmp2 = SAFETRANSLATE(field_option_list_); + res = new IR(IRTYPE::kFieldOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void FieldOptionList::deep_delete() { + SAFEDELETE(field_option_); + SAFEDELETE(field_option_list_); + delete this; +} + +IR* FieldOption::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kFieldOption, OP3(TERMINAL::tSigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kFieldOption, OP3(TERMINAL::tUnsigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kFieldOption, OP3(TERMINAL::tZerofill, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void FieldOption::deep_delete() { + delete this; +} + +IR* OptColumnAttributeList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_attribute_list_); + res = new IR(IRTYPE::kOptColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptColumnAttributeList::deep_delete() { + SAFEDELETE(column_attribute_list_); + delete this; +} + +IR* ColumnAttributeList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(column_attribute_); + res = new IR(IRTYPE::kColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_attribute_); + auto tmp2 = SAFETRANSLATE(column_attribute_list_); + res = new IR(IRTYPE::kColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ColumnAttributeList::deep_delete() { + SAFEDELETE(column_attribute_); + SAFEDELETE(column_attribute_list_); + delete this; +} + +IR* ColumnAttribute::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(not_null_); + res = new IR(IRTYPE::kColumnAttribute, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(default_attribute_); + res = new IR(IRTYPE::kColumnAttribute, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(visibility_); + res = new IR(IRTYPE::kColumnAttribute, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ColumnAttribute::deep_delete() { + SAFEDELETE(not_null_); + SAFEDELETE(default_attribute_); + SAFEDELETE(visibility_); + delete this; +} + +IR* DefaultAttribute::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kDefaultAttribute, OP3(TERMINAL::tDefaultOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void DefaultAttribute::deep_delete() { + SAFEDELETE(expr_root_); + delete this; +} + +IR* NotNull::translate() { + TRANSLATESTART + + res = new IR(IRTYPE::kNotNull, OP3(TERMINAL::tNotNull, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + + TRANSLATEEND +} + +void NotNull::deep_delete() { + delete this; +} + +IR* Visibility::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kVisibility, OP3(TERMINAL::tVisible, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kVisibility, OP3(TERMINAL::tInvisible, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Visibility::deep_delete() { + delete this; +} + +IR* OptConstraintName::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptConstraintName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(constraint_name_); + res = new IR(IRTYPE::kOptConstraintName, OP3(TERMINAL::tConstraint, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptConstraintName::deep_delete() { + SAFEDELETE(constraint_name_); + delete this; +} + +IR* CheckConstraint::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kCheckConstraint, OP3(TERMINAL::tCheckOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void CheckConstraint::deep_delete() { + SAFEDELETE(expr_root_); + delete this; +} + +IR* TableConstraintDef::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_index_name_); + auto tmp2 = SAFETRANSLATE(key_list_with_expression_); + res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tIndex, TERMINAL::tOpLp, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_constraint_name_); + auto tmp2 = SAFETRANSLATE(constraint_key_type_); + auto tmp3 = SAFETRANSLATE(opt_index_name_); + auto tmp4 = SAFETRANSLATE(key_list_with_expression_); + auto tmp5 = new IR(IRTYPE::kTableConstraintDefTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tOpRp), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kTableConstraintDefTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(opt_constraint_name_); + auto tmp2 = SAFETRANSLATE(check_constraint_); + res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(opt_constraint_name_); + auto tmp2 = SAFETRANSLATE(opt_index_name_); + auto tmp3 = SAFETRANSLATE(key_list_); + auto tmp4 = SAFETRANSLATE(references_); + auto tmp5 = new IR(IRTYPE::kTableConstraintDefTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kTableConstraintDefTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tEmpty, TERMINAL::tForeignKey, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableConstraintDef::deep_delete() { + SAFEDELETE(key_list_with_expression_); + SAFEDELETE(opt_index_name_); + SAFEDELETE(constraint_key_type_); + SAFEDELETE(opt_constraint_name_); + SAFEDELETE(check_constraint_); + SAFEDELETE(references_); + SAFEDELETE(key_list_); + delete this; +} + +IR* References::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(column_list_); + auto tmp3 = SAFETRANSLATE(opt_on_update_delete_); + auto tmp4 = new IR(IRTYPE::kReferencesTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kReferences, OP3(TERMINAL::tReferences, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp1, tmp4); + + TRANSLATEEND +} + +void References::deep_delete() { + SAFEDELETE(opt_on_update_delete_); + SAFEDELETE(column_list_); + SAFEDELETE(table_name_); + delete this; +} + +IR* OptOnUpdateDelete::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(on_update_option_1_); + res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnUpdate, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(on_update_option_1_); + res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnDelete, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(on_update_option_1_); + auto tmp2 = SAFETRANSLATE(on_update_option_2_); + res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnUpdate, TERMINAL::tOnDelete, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(on_update_option_1_); + auto tmp2 = SAFETRANSLATE(on_update_option_2_); + res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnDelete, TERMINAL::tOnUpdate, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptOnUpdateDelete::deep_delete() { + SAFEDELETE(on_update_option_1_); + SAFEDELETE(on_update_option_2_); + delete this; +} + +IR* OnUpdateOption::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tCascade, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tSetNull, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tNoAction, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tSetDefault, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OnUpdateOption::deep_delete() { + delete this; +} + +IR* KeyList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(key_part_); + res = new IR(IRTYPE::kKeyList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(key_part_); + auto tmp2 = SAFETRANSLATE(key_list_); + res = new IR(IRTYPE::kKeyList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void KeyList::deep_delete() { + SAFEDELETE(key_part_); + SAFEDELETE(key_list_); + delete this; +} + +IR* KeyListWithExpression::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(key_part_with_expression_); + res = new IR(IRTYPE::kKeyListWithExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(key_part_with_expression_); + auto tmp2 = SAFETRANSLATE(key_list_with_expression_); + res = new IR(IRTYPE::kKeyListWithExpression, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void KeyListWithExpression::deep_delete() { + SAFEDELETE(key_part_with_expression_); + SAFEDELETE(key_list_with_expression_); + delete this; +} + +IR* KeyPartWithExpression::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(key_part_); + res = new IR(IRTYPE::kKeyPartWithExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_root_); + auto tmp2 = SAFETRANSLATE(opt_ordering_direction_); + res = new IR(IRTYPE::kKeyPartWithExpression, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void KeyPartWithExpression::deep_delete() { + SAFEDELETE(key_part_); + SAFEDELETE(opt_ordering_direction_); + SAFEDELETE(expr_root_); + delete this; +} + +IR* KeyPart::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(column_name_); + auto tmp2 = SAFETRANSLATE(opt_ordering_direction_); + res = new IR(IRTYPE::kKeyPart, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_name_); + auto tmp2 = SAFETRANSLATE(iconst_); + auto tmp3 = SAFETRANSLATE(opt_ordering_direction_); + auto tmp4 = new IR(IRTYPE::kKeyPartTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kKeyPart, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void KeyPart::deep_delete() { + SAFEDELETE(opt_ordering_direction_); + SAFEDELETE(column_name_); + SAFEDELETE(iconst_); + delete this; +} + +IR* ConstraintKeyType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kConstraintKeyType, OP3(TERMINAL::tPrimaryKey, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kConstraintKeyType, OP3(TERMINAL::tUnique, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ConstraintKeyType::deep_delete() { + delete this; +} + +IR* OptIndexName::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptIndexName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(index_name_); + res = new IR(IRTYPE::kOptIndexName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptIndexName::deep_delete() { + SAFEDELETE(index_name_); + delete this; +} + +IR* SelectStmt::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(query_expression_); + res = new IR(IRTYPE::kSelectStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void SelectStmt::deep_delete() { + SAFEDELETE(query_expression_); + delete this; +} + +IR* QueryExpression::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(query_expression_body_); + auto tmp2 = SAFETRANSLATE(opt_order_clause_); + auto tmp3 = SAFETRANSLATE(opt_limit_clause_); + auto tmp4 = new IR(IRTYPE::kQueryExpressionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kQueryExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(with_clause_); + auto tmp2 = SAFETRANSLATE(query_expression_body_); + auto tmp3 = SAFETRANSLATE(opt_order_clause_); + auto tmp4 = SAFETRANSLATE(opt_limit_clause_); + auto tmp5 = new IR(IRTYPE::kQueryExpressionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kQueryExpressionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kQueryExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void QueryExpression::deep_delete() { + SAFEDELETE(opt_limit_clause_); + SAFEDELETE(opt_order_clause_); + SAFEDELETE(query_expression_body_); + SAFEDELETE(with_clause_); + delete this; +} + +IR* QueryExpressionBody::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(query_primary_); + res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(query_expression_parens_); + res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(query_expression_body_1_); + auto tmp2 = SAFETRANSLATE(opt_union_option_); + auto tmp3 = SAFETRANSLATE(query_expression_body_2_); + auto tmp4 = new IR(IRTYPE::kQueryExpressionBodyTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tUnion, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(query_expression_body_1_); + auto tmp2 = SAFETRANSLATE(opt_union_option_); + auto tmp3 = SAFETRANSLATE(query_expression_body_2_); + auto tmp4 = new IR(IRTYPE::kQueryExpressionBodyTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tExcept, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(query_expression_body_1_); + auto tmp2 = SAFETRANSLATE(opt_union_option_); + auto tmp3 = SAFETRANSLATE(query_expression_body_2_); + auto tmp4 = new IR(IRTYPE::kQueryExpressionBodyTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tIntersect, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void QueryExpressionBody::deep_delete() { + SAFEDELETE(query_primary_); + SAFEDELETE(query_expression_parens_); + SAFEDELETE(query_expression_body_1_); + SAFEDELETE(query_expression_body_2_); + SAFEDELETE(opt_union_option_); + delete this; +} + +IR* QueryPrimary::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(query_specification_); + res = new IR(IRTYPE::kQueryPrimary, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void QueryPrimary::deep_delete() { + SAFEDELETE(query_specification_); + delete this; +} + +IR* QuerySpecification::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_select_options_); + auto tmp2 = SAFETRANSLATE(select_item_list_); + auto tmp3 = SAFETRANSLATE(opt_from_clause_); + auto tmp4 = SAFETRANSLATE(opt_where_clause_); + auto tmp5 = SAFETRANSLATE(opt_group_clause_); + auto tmp6 = SAFETRANSLATE(opt_having_clause_); + auto tmp7 = SAFETRANSLATE(opt_window_clause_); + auto tmp8 = new IR(IRTYPE::kQuerySpecificationTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp6, tmp7); + auto tmp9 = new IR(IRTYPE::kQuerySpecificationTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp8); + auto tmp10 = new IR(IRTYPE::kQuerySpecificationTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp9); + auto tmp11 = new IR(IRTYPE::kQuerySpecificationTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp10); + auto tmp12 = new IR(IRTYPE::kQuerySpecificationTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp11); + res = new IR(IRTYPE::kQuerySpecification, OP3(TERMINAL::tSelect, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp12); + + TRANSLATEEND +} + +void QuerySpecification::deep_delete() { + SAFEDELETE(opt_window_clause_); + SAFEDELETE(opt_having_clause_); + SAFEDELETE(opt_group_clause_); + SAFEDELETE(opt_where_clause_); + SAFEDELETE(opt_from_clause_); + SAFEDELETE(select_item_list_); + SAFEDELETE(opt_select_options_); + delete this; +} + +IR* OptWindowClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptWindowClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(window_definition_list_); + res = new IR(IRTYPE::kOptWindowClause, OP3(TERMINAL::tWindow, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptWindowClause::deep_delete() { + SAFEDELETE(window_definition_list_); + delete this; +} + +IR* WindowDefinitionList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(window_definition_); + res = new IR(IRTYPE::kWindowDefinitionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(window_definition_); + auto tmp2 = SAFETRANSLATE(window_definition_list_); + res = new IR(IRTYPE::kWindowDefinitionList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowDefinitionList::deep_delete() { + SAFEDELETE(window_definition_); + SAFEDELETE(window_definition_list_); + delete this; +} + +IR* WindowDefinition::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(window_name_); + auto tmp2 = SAFETRANSLATE(window_spec_); + res = new IR(IRTYPE::kWindowDefinition, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void WindowDefinition::deep_delete() { + SAFEDELETE(window_spec_); + SAFEDELETE(window_name_); + delete this; +} + +IR* WindowSpec::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(window_spec_details_); + res = new IR(IRTYPE::kWindowSpec, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void WindowSpec::deep_delete() { + SAFEDELETE(window_spec_details_); + delete this; +} + +IR* WindowSpecDetails::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_existing_window_name_); + auto tmp2 = SAFETRANSLATE(opt_partition_clause_); + auto tmp3 = SAFETRANSLATE(opt_window_order_by_clause_); + auto tmp4 = SAFETRANSLATE(opt_window_frame_clause_); + auto tmp5 = new IR(IRTYPE::kWindowSpecDetailsTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kWindowSpecDetailsTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kWindowSpecDetails, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + + TRANSLATEEND +} + +void WindowSpecDetails::deep_delete() { + SAFEDELETE(opt_window_frame_clause_); + SAFEDELETE(opt_window_order_by_clause_); + SAFEDELETE(opt_partition_clause_); + SAFEDELETE(opt_existing_window_name_); + delete this; +} + +IR* OptExistingWindowName::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptExistingWindowName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(window_name_); + res = new IR(IRTYPE::kOptExistingWindowName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptExistingWindowName::deep_delete() { + SAFEDELETE(window_name_); + delete this; +} + +IR* OptPartitionClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptPartitionClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_root_list_); + res = new IR(IRTYPE::kOptPartitionClause, OP3(TERMINAL::tPartitionBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptPartitionClause::deep_delete() { + SAFEDELETE(expr_root_list_); + delete this; +} + +IR* OptWindowOrderByClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptWindowOrderByClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(order_list_); + res = new IR(IRTYPE::kOptWindowOrderByClause, OP3(TERMINAL::tOrderBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptWindowOrderByClause::deep_delete() { + SAFEDELETE(order_list_); + delete this; +} + +IR* OrderList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(order_expr_); + res = new IR(IRTYPE::kOrderList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(order_expr_); + auto tmp2 = SAFETRANSLATE(order_list_); + res = new IR(IRTYPE::kOrderList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OrderList::deep_delete() { + SAFEDELETE(order_expr_); + SAFEDELETE(order_list_); + delete this; +} + +IR* OrderExpr::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(expr_root_); + auto tmp2 = SAFETRANSLATE(opt_ordering_direction_); + res = new IR(IRTYPE::kOrderExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void OrderExpr::deep_delete() { + SAFEDELETE(opt_ordering_direction_); + SAFEDELETE(expr_root_); + delete this; +} + +IR* OptOrderingDirection::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptOrderingDirection, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptOrderingDirection, OP3(TERMINAL::tAsc, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOptOrderingDirection, OP3(TERMINAL::tDesc, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptOrderingDirection::deep_delete() { + delete this; +} + +IR* OptWindowFrameClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptWindowFrameClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(window_frame_units_); + auto tmp2 = SAFETRANSLATE(window_frame_extent_); + res = new IR(IRTYPE::kOptWindowFrameClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptWindowFrameClause::deep_delete() { + SAFEDELETE(window_frame_extent_); + SAFEDELETE(window_frame_units_); + delete this; +} + +IR* WindowFrameUnits::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kWindowFrameUnits, OP3(TERMINAL::tRows, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kWindowFrameUnits, OP3(TERMINAL::tRange, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowFrameUnits::deep_delete() { + delete this; +} + +IR* WindowFrameExtent::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(window_frame_start_); + res = new IR(IRTYPE::kWindowFrameExtent, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(window_frame_between_); + res = new IR(IRTYPE::kWindowFrameExtent, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowFrameExtent::deep_delete() { + SAFEDELETE(window_frame_start_); + SAFEDELETE(window_frame_between_); + delete this; +} + +IR* WindowFrameStart::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kWindowFrameStart, OP3(TERMINAL::tUnboundedPreceding, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(iconst_); + res = new IR(IRTYPE::kWindowFrameStart, OP3(TERMINAL::tEmpty, TERMINAL::tPreceding, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kWindowFrameStart, OP3(TERMINAL::tCurrentRow, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowFrameStart::deep_delete() { + SAFEDELETE(iconst_); + delete this; +} + +IR* WindowFrameBetween::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(window_frame_start_); + auto tmp2 = SAFETRANSLATE(window_frame_bound_); + res = new IR(IRTYPE::kWindowFrameBetween, OP3(TERMINAL::tBetween, TERMINAL::tAnd, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void WindowFrameBetween::deep_delete() { + SAFEDELETE(window_frame_bound_); + SAFEDELETE(window_frame_start_); + delete this; +} + +IR* WindowFrameBound::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(window_frame_start_); + res = new IR(IRTYPE::kWindowFrameBound, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kWindowFrameBound, OP3(TERMINAL::tUnboundedFollowing, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(iconst_); + res = new IR(IRTYPE::kWindowFrameBound, OP3(TERMINAL::tEmpty, TERMINAL::tFollowing, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowFrameBound::deep_delete() { + SAFEDELETE(window_frame_start_); + SAFEDELETE(iconst_); + delete this; +} + +IR* OptHavingClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptHavingClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kOptHavingClause, OP3(TERMINAL::tHaving, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptHavingClause::deep_delete() { + SAFEDELETE(expr_root_); + delete this; +} + +IR* OptGroupClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptGroupClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_root_list_); + auto tmp2 = SAFETRANSLATE(olap_opt_); + res = new IR(IRTYPE::kOptGroupClause, OP3(TERMINAL::tGroupBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptGroupClause::deep_delete() { + SAFEDELETE(olap_opt_); + SAFEDELETE(expr_root_list_); + delete this; +} + +IR* OlapOpt::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOlapOpt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOlapOpt, OP3(TERMINAL::tWithRollup, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OlapOpt::deep_delete() { + delete this; +} + +IR* OptWhereClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptWhereClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(where_clause_); + res = new IR(IRTYPE::kOptWhereClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptWhereClause::deep_delete() { + SAFEDELETE(where_clause_); + delete this; +} + +IR* WhereClause::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kWhereClause, OP3(TERMINAL::tWhere, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void WhereClause::deep_delete() { + SAFEDELETE(expr_root_); + delete this; +} + +IR* OptFromClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptFromClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(from_clause_); + res = new IR(IRTYPE::kOptFromClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptFromClause::deep_delete() { + SAFEDELETE(from_clause_); + delete this; +} + +IR* FromClause::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(table_reference_list_); + res = new IR(IRTYPE::kFromClause, OP3(TERMINAL::tFrom, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void FromClause::deep_delete() { + SAFEDELETE(table_reference_list_); + delete this; +} + +IR* TableReferenceList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(table_reference_); + res = new IR(IRTYPE::kTableReferenceList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_reference_); + auto tmp2 = SAFETRANSLATE(table_reference_list_); + res = new IR(IRTYPE::kTableReferenceList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableReferenceList::deep_delete() { + SAFEDELETE(table_reference_); + SAFEDELETE(table_reference_list_); + delete this; +} + +IR* TableReference::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(table_factor_); + res = new IR(IRTYPE::kTableReference, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(joined_table_); + res = new IR(IRTYPE::kTableReference, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableReference::deep_delete() { + SAFEDELETE(table_factor_); + SAFEDELETE(joined_table_); + delete this; +} + +IR* TableFactor::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(single_table_); + res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(derived_table_); + res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(joined_table_parens_); + res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(table_reference_list_parens_); + res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableFactor::deep_delete() { + SAFEDELETE(single_table_); + SAFEDELETE(derived_table_); + SAFEDELETE(joined_table_parens_); + SAFEDELETE(table_reference_list_parens_); + delete this; +} + +IR* TableReferenceListParens::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(table_reference_); + auto tmp2 = SAFETRANSLATE(table_reference_list_); + res = new IR(IRTYPE::kTableReferenceListParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + + TRANSLATEEND +} + +void TableReferenceListParens::deep_delete() { + SAFEDELETE(table_reference_list_); + SAFEDELETE(table_reference_); + delete this; +} + +IR* JoinedTableParens::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(joined_table_); + res = new IR(IRTYPE::kJoinedTableParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void JoinedTableParens::deep_delete() { + SAFEDELETE(joined_table_); + delete this; +} + +IR* DerivedTable::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(subquery_); + auto tmp2 = SAFETRANSLATE(alias_); + auto tmp3 = SAFETRANSLATE(opt_column_list_); + auto tmp4 = new IR(IRTYPE::kDerivedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kDerivedTable, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(subquery_); + auto tmp2 = SAFETRANSLATE(alias_); + auto tmp3 = SAFETRANSLATE(opt_column_list_); + auto tmp4 = new IR(IRTYPE::kDerivedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kDerivedTable, OP3(TERMINAL::tLateral, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void DerivedTable::deep_delete() { + SAFEDELETE(opt_column_list_); + SAFEDELETE(alias_); + SAFEDELETE(subquery_); + delete this; +} + +IR* OptColumnList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptColumnList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_list_); + res = new IR(IRTYPE::kOptColumnList, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptColumnList::deep_delete() { + SAFEDELETE(column_list_); + delete this; +} + +IR* ColumnList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(column_name_); + res = new IR(IRTYPE::kColumnList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(column_name_); + auto tmp2 = SAFETRANSLATE(column_list_); + res = new IR(IRTYPE::kColumnList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ColumnList::deep_delete() { + SAFEDELETE(column_name_); + SAFEDELETE(column_list_); + delete this; +} + +IR* Subquery::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(query_expression_parens_); + res = new IR(IRTYPE::kSubquery, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void Subquery::deep_delete() { + SAFEDELETE(query_expression_parens_); + delete this; +} + +IR* SingleTable::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(opt_alias_); + res = new IR(IRTYPE::kSingleTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void SingleTable::deep_delete() { + SAFEDELETE(opt_alias_); + SAFEDELETE(table_name_); + delete this; +} + +IR* OptAlias::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(alias_); + res = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptAlias::deep_delete() { + SAFEDELETE(alias_); + delete this; +} + +IR* JoinedTable::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(table_reference_1_); + auto tmp2 = SAFETRANSLATE(inner_join_type_); + auto tmp3 = SAFETRANSLATE(table_reference_2_); + auto tmp4 = SAFETRANSLATE(expr_root_); + auto tmp5 = new IR(IRTYPE::kJoinedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOn, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kJoinedTableTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_reference_1_); + auto tmp2 = SAFETRANSLATE(inner_join_type_); + auto tmp3 = SAFETRANSLATE(table_reference_2_); + auto tmp4 = SAFETRANSLATE(column_list_); + auto tmp5 = new IR(IRTYPE::kJoinedTableTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tUsingOpLp, TERMINAL::tOpRp), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kJoinedTableTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(table_reference_1_); + auto tmp2 = SAFETRANSLATE(outer_join_type_); + auto tmp3 = SAFETRANSLATE(table_reference_2_); + auto tmp4 = SAFETRANSLATE(expr_root_); + auto tmp5 = new IR(IRTYPE::kJoinedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOn, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kJoinedTableTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(table_reference_1_); + auto tmp2 = SAFETRANSLATE(outer_join_type_); + auto tmp3 = SAFETRANSLATE(table_reference_2_); + auto tmp4 = SAFETRANSLATE(column_list_); + auto tmp5 = new IR(IRTYPE::kJoinedTableTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tUsingOpLp, TERMINAL::tOpRp), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kJoinedTableTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(table_reference_1_); + auto tmp2 = SAFETRANSLATE(inner_join_type_); + auto tmp3 = SAFETRANSLATE(table_reference_2_); + auto tmp4 = new IR(IRTYPE::kJoinedTableTmp7, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(table_reference_1_); + auto tmp2 = SAFETRANSLATE(natural_join_type_); + auto tmp3 = SAFETRANSLATE(table_factor_); + auto tmp4 = new IR(IRTYPE::kJoinedTableTmp8, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void JoinedTable::deep_delete() { + SAFEDELETE(expr_root_); + SAFEDELETE(table_reference_1_); + SAFEDELETE(table_reference_2_); + SAFEDELETE(inner_join_type_); + SAFEDELETE(column_list_); + SAFEDELETE(outer_join_type_); + SAFEDELETE(table_factor_); + SAFEDELETE(natural_join_type_); + delete this; +} + +IR* InnerJoinType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tInnerJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tCrossJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tStraightJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void InnerJoinType::deep_delete() { + delete this; +} + +IR* NaturalJoinType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_inner_); + res = new IR(IRTYPE::kNaturalJoinType, OP3(TERMINAL::tNatural, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_outer_); + res = new IR(IRTYPE::kNaturalJoinType, OP3(TERMINAL::tNaturalRight, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(opt_outer_); + res = new IR(IRTYPE::kNaturalJoinType, OP3(TERMINAL::tNaturalLeft, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void NaturalJoinType::deep_delete() { + SAFEDELETE(opt_inner_); + SAFEDELETE(opt_outer_); + delete this; +} + +IR* OptInner::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptInner, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptInner, OP3(TERMINAL::tInner, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptInner::deep_delete() { + delete this; +} + +IR* OptOuter::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptOuter, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptOuter, OP3(TERMINAL::tOuter, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptOuter::deep_delete() { + delete this; +} + +IR* OuterJoinType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_outer_); + res = new IR(IRTYPE::kOuterJoinType, OP3(TERMINAL::tLeft, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_outer_); + res = new IR(IRTYPE::kOuterJoinType, OP3(TERMINAL::tRight, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OuterJoinType::deep_delete() { + SAFEDELETE(opt_outer_); + delete this; +} + +IR* SelectItemList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(select_item_); + res = new IR(IRTYPE::kSelectItemList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(select_item_); + auto tmp2 = SAFETRANSLATE(select_item_list_); + res = new IR(IRTYPE::kSelectItemList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void SelectItemList::deep_delete() { + SAFEDELETE(select_item_); + SAFEDELETE(select_item_list_); + delete this; +} + +IR* SelectItem::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(table_wild_); + res = new IR(IRTYPE::kSelectItem, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_root_); + auto tmp2 = SAFETRANSLATE(opt_alias_); + res = new IR(IRTYPE::kSelectItem, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void SelectItem::deep_delete() { + SAFEDELETE(table_wild_); + SAFEDELETE(opt_alias_); + SAFEDELETE(expr_root_); + delete this; +} + +IR* TableWild::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kTableWild, OP3(TERMINAL::tOpMul, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_name_); + res = new IR(IRTYPE::kTableWild, OP3(TERMINAL::tEmpty, TERMINAL::tOpDotOpMul, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TableWild::deep_delete() { + SAFEDELETE(table_name_); + delete this; +} + +IR* OptSelectOptions::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptSelectOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(select_option_list_); + res = new IR(IRTYPE::kOptSelectOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptSelectOptions::deep_delete() { + SAFEDELETE(select_option_list_); + delete this; +} + +IR* SelectOptionList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(select_option_); + res = new IR(IRTYPE::kSelectOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(select_option_); + auto tmp2 = SAFETRANSLATE(select_option_list_); + res = new IR(IRTYPE::kSelectOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void SelectOptionList::deep_delete() { + SAFEDELETE(select_option_); + SAFEDELETE(select_option_list_); + delete this; +} + +IR* SelectOption::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlNoCache, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tStraightJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tHighPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tDistinct, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(4) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlSmallResult, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(5) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlBigResult, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(6) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlBufferResult, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(7) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlCalcFoundRows, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(8) + res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tAll, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void SelectOption::deep_delete() { + delete this; +} + +IR* QueryExpressionParens::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(query_expression_parens_); + res = new IR(IRTYPE::kQueryExpressionParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(query_expression_); + res = new IR(IRTYPE::kQueryExpressionParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void QueryExpressionParens::deep_delete() { + SAFEDELETE(query_expression_parens_); + SAFEDELETE(query_expression_); + delete this; +} + +IR* OptUnionOption::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptUnionOption, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptUnionOption, OP3(TERMINAL::tDistinct, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOptUnionOption, OP3(TERMINAL::tAll, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptUnionOption::deep_delete() { + delete this; +} + +IR* OptOrderClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptOrderClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(order_clause_); + res = new IR(IRTYPE::kOptOrderClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptOrderClause::deep_delete() { + SAFEDELETE(order_clause_); + delete this; +} + +IR* OrderClause::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(order_list_); + res = new IR(IRTYPE::kOrderClause, OP3(TERMINAL::tOrderBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void OrderClause::deep_delete() { + SAFEDELETE(order_list_); + delete this; +} + +IR* OptLimitClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptLimitClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(limit_clause_); + res = new IR(IRTYPE::kOptLimitClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptLimitClause::deep_delete() { + SAFEDELETE(limit_clause_); + delete this; +} + +IR* LimitClause::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(limit_options_); + res = new IR(IRTYPE::kLimitClause, OP3(TERMINAL::tLimit, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void LimitClause::deep_delete() { + SAFEDELETE(limit_options_); + delete this; +} + +IR* LimitOptions::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(iconst_1_); + res = new IR(IRTYPE::kLimitOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(iconst_1_); + auto tmp2 = SAFETRANSLATE(iconst_2_); + res = new IR(IRTYPE::kLimitOptions, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void LimitOptions::deep_delete() { + SAFEDELETE(iconst_1_); + SAFEDELETE(iconst_2_); + delete this; +} + +IR* WithClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(with_list_); + res = new IR(IRTYPE::kWithClause, OP3(TERMINAL::tWith, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(with_list_); + res = new IR(IRTYPE::kWithClause, OP3(TERMINAL::tWithRecursive, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WithClause::deep_delete() { + SAFEDELETE(with_list_); + delete this; +} + +IR* WithList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(common_table_expr_); + res = new IR(IRTYPE::kWithList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(common_table_expr_); + auto tmp2 = SAFETRANSLATE(with_list_); + res = new IR(IRTYPE::kWithList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WithList::deep_delete() { + SAFEDELETE(common_table_expr_); + SAFEDELETE(with_list_); + delete this; +} + +IR* CommonTableExpr::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(opt_column_list_); + auto tmp3 = SAFETRANSLATE(subquery_); + auto tmp4 = new IR(IRTYPE::kCommonTableExprTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kCommonTableExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + + TRANSLATEEND +} + +void CommonTableExpr::deep_delete() { + SAFEDELETE(subquery_); + SAFEDELETE(opt_column_list_); + SAFEDELETE(table_name_); + delete this; +} + +IR* ExprRootList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_root_); + res = new IR(IRTYPE::kExprRootList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_root_); + auto tmp2 = SAFETRANSLATE(expr_root_list_); + res = new IR(IRTYPE::kExprRootList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ExprRootList::deep_delete() { + SAFEDELETE(expr_root_); + SAFEDELETE(expr_root_list_); + delete this; +} + +IR* ExprRoot::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kExprRoot, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void ExprRoot::deep_delete() { + SAFEDELETE(expr_); + delete this; +} + +IR* Expr::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOr, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tXor, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tNot, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsTrue, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotTrue, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsFalse, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotFalse, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsUnknown, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotUnknown, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Expr::deep_delete() { + SAFEDELETE(expr_1_); + SAFEDELETE(expr_2_); + SAFEDELETE(bool_pri_); + delete this; +} + +IR* BoolPri::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tIsNull, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(bool_pri_); + res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotNull, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(bool_pri_); + auto tmp2 = SAFETRANSLATE(comp_op_); + auto tmp3 = SAFETRANSLATE(predicate_); + auto tmp4 = new IR(IRTYPE::kBoolPriTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(bool_pri_); + auto tmp2 = SAFETRANSLATE(comp_op_); + auto tmp3 = SAFETRANSLATE(all_subquery_); + auto tmp4 = new IR(IRTYPE::kBoolPriTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(predicate_); + res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void BoolPri::deep_delete() { + SAFEDELETE(bool_pri_); + SAFEDELETE(predicate_); + SAFEDELETE(comp_op_); + SAFEDELETE(all_subquery_); + delete this; +} + +IR* Predicate::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(in_subquery_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tInOpLp, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(expr_); + auto tmp3 = SAFETRANSLATE(expr_list_); + auto tmp4 = new IR(IRTYPE::kPredicateTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tInOpLp, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotInOpLp, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(expr_); + auto tmp3 = SAFETRANSLATE(expr_list_); + auto tmp4 = new IR(IRTYPE::kPredicateTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotInOpLp, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + auto tmp3 = SAFETRANSLATE(predicate_); + auto tmp4 = new IR(IRTYPE::kPredicateTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tBetween, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + auto tmp3 = SAFETRANSLATE(predicate_); + auto tmp4 = new IR(IRTYPE::kPredicateTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotBetween, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tSoundsLike, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(simple_expr_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tLike, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(simple_expr_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotLike, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tRegexp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(11) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotRegexp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(12) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Predicate::deep_delete() { + SAFEDELETE(in_subquery_); + SAFEDELETE(bit_expr_1_); + SAFEDELETE(bit_expr_2_); + SAFEDELETE(expr_); + SAFEDELETE(expr_list_); + SAFEDELETE(predicate_); + SAFEDELETE(simple_expr_); + delete this; +} + +IR* BitExpr::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpOr, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpAnd, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpShl, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpShr, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpAdd, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpSub, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpMul, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpDivide, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpMod, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(bit_expr_1_); + auto tmp2 = SAFETRANSLATE(bit_expr_2_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpXor, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(simple_expr_); + res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void BitExpr::deep_delete() { + SAFEDELETE(bit_expr_1_); + SAFEDELETE(bit_expr_2_); + SAFEDELETE(simple_expr_); + delete this; +} + +IR* SimpleExpr::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(columnref_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(literal_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(iconst_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(fconst_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(sconst_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(simple_expr_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpAdd, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(simple_expr_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpSub, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(simple_expr_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpNot, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tExists, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(type_cast_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(11) + auto tmp1 = SAFETRANSLATE(case_expr_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(12) + auto tmp1 = SAFETRANSLATE(columnref_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tDefaultOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(13) + auto tmp1 = SAFETRANSLATE(function_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(14) + auto tmp1 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void SimpleExpr::deep_delete() { + SAFEDELETE(columnref_); + SAFEDELETE(literal_); + SAFEDELETE(iconst_); + SAFEDELETE(fconst_); + SAFEDELETE(sconst_); + SAFEDELETE(simple_expr_); + SAFEDELETE(subquery_); + SAFEDELETE(type_cast_); + SAFEDELETE(case_expr_); + SAFEDELETE(function_); + SAFEDELETE(expr_); + delete this; +} + +IR* Function::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(control_function_); + res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(math_function_); + res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(string_function_); + res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(aggregate_function_); + res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(window_function_); + res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Function::deep_delete() { + SAFEDELETE(control_function_); + SAFEDELETE(math_function_); + SAFEDELETE(string_function_); + SAFEDELETE(aggregate_function_); + SAFEDELETE(window_function_); + delete this; +} + +IR* StringFunction::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tAsciiOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tBinOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tBitLengthOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tCharLengthOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLengthOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLowerOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLtrimOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tOctOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tOrdOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tQuoteOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tReverseOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(11) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRtrimOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(12) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSpaceOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(13) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(14) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpLeadingFrom, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(15) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpTrailingFrom, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(16) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tUnhexOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(17) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tUpperOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(18) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tFindInSetOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(19) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tInstrOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(20) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLeftOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(21) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLocateOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(22) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRepeatOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(23) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRightOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(24) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSubstringOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(25) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpLeading, TERMINAL::tFrom, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(26) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpTrailing, TERMINAL::tFrom, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(27) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLp, TERMINAL::tFrom, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(28) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tExportSetOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(29) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLocateOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(30) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLpadOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(31) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tReplaceOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(32) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRpadOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(33) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSubstringOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(34) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSubstringIndexOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(35) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = SAFETRANSLATE(expr_4_); + auto tmp5 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kStringFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tExportSetOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(36) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = SAFETRANSLATE(expr_4_); + auto tmp5 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kStringFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tInsertOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(37) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = SAFETRANSLATE(expr_4_); + auto tmp5 = SAFETRANSLATE(expr_5_); + auto tmp6 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kStringFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kStringFunctionTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tExportSetOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp8); + CASEEND + CASESTART(38) + auto tmp1 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tCharOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(39) + auto tmp1 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tConcatOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(40) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tConcatWsOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(41) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tEltOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(42) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tFieldOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(43) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tMakeSetOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void StringFunction::deep_delete() { + SAFEDELETE(expr_1_); + SAFEDELETE(expr_2_); + SAFEDELETE(expr_3_); + SAFEDELETE(expr_4_); + SAFEDELETE(expr_5_); + SAFEDELETE(expr_list_); + delete this; +} + +IR* MathFunction::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tPiOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAbsOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAcosOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAsinOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAtanOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tCeilingOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tCosOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tCotOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tDegreesOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tExpOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(11) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tFloorOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(12) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tHexOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(13) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tLnOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(14) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRadiansOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(15) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(16) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRoundOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(17) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tSignOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(18) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tSinOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(19) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tSqrtOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(20) + auto tmp1 = SAFETRANSLATE(expr_1_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tTanOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(21) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAtanOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(22) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tFormatOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(23) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tLogOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(24) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tModOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(25) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tPowOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(26) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRoundOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(27) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tTruncateOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(28) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kMathFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tConvOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void MathFunction::deep_delete() { + SAFEDELETE(expr_1_); + SAFEDELETE(expr_2_); + SAFEDELETE(expr_3_); + delete this; +} + +IR* WindowFunction::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tRowNumberOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tRankOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tDenseRankOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tCumeDistOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tPercentRankOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(iconst_); + auto tmp2 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tNtileOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_lead_lag_info_); + auto tmp3 = SAFETRANSLATE(opt_null_treatment_); + auto tmp4 = SAFETRANSLATE(windowing_clause_); + auto tmp5 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kWindowFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tLeadOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_lead_lag_info_); + auto tmp3 = SAFETRANSLATE(opt_null_treatment_); + auto tmp4 = SAFETRANSLATE(windowing_clause_); + auto tmp5 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); + auto tmp6 = new IR(IRTYPE::kWindowFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp5); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tLagOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_null_treatment_); + auto tmp3 = SAFETRANSLATE(windowing_clause_); + auto tmp4 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tFirstValueOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_null_treatment_); + auto tmp3 = SAFETRANSLATE(windowing_clause_); + auto tmp4 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tLastValueOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(iconst_); + auto tmp3 = SAFETRANSLATE(opt_from_first_last_); + auto tmp4 = SAFETRANSLATE(opt_null_treatment_); + auto tmp5 = SAFETRANSLATE(windowing_clause_); + auto tmp6 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kWindowFunctionTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kWindowFunctionTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tNthValueOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp8); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowFunction::deep_delete() { + SAFEDELETE(windowing_clause_); + SAFEDELETE(iconst_); + SAFEDELETE(opt_null_treatment_); + SAFEDELETE(opt_lead_lag_info_); + SAFEDELETE(expr_); + SAFEDELETE(opt_from_first_last_); + delete this; +} + +IR* OptNullTreatment::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptNullTreatment, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptNullTreatment, OP3(TERMINAL::tRespectNulls, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOptNullTreatment, OP3(TERMINAL::tIgnoreNulls, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptNullTreatment::deep_delete() { + delete this; +} + +IR* OptFromFirstLast::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptFromFirstLast, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptFromFirstLast, OP3(TERMINAL::tFromFirst, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kOptFromFirstLast, OP3(TERMINAL::tFromLast, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptFromFirstLast::deep_delete() { + delete this; +} + +IR* OptLeadLagInfo::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptLeadLagInfo, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(lead_lag_info_); + res = new IR(IRTYPE::kOptLeadLagInfo, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptLeadLagInfo::deep_delete() { + SAFEDELETE(lead_lag_info_); + delete this; +} + +IR* LeadLagInfo::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(iconst_); + res = new IR(IRTYPE::kLeadLagInfo, OP3(TERMINAL::tOpComma, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(iconst_); + auto tmp2 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kLeadLagInfo, OP3(TERMINAL::tOpComma, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void LeadLagInfo::deep_delete() { + SAFEDELETE(iconst_); + SAFEDELETE(expr_); + delete this; +} + +IR* AggregateFunction::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_distinct_); + auto tmp2 = SAFETRANSLATE(expr_); + auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); + auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tAvgOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tBitAndOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tBitOrOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(3) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tBitXorOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(4) + auto tmp1 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tCountOpLpOpMulOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tCountOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(6) + auto tmp1 = SAFETRANSLATE(expr_list_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tCountOpLpDistinct, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(opt_distinct_); + auto tmp2 = SAFETRANSLATE(expr_); + auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); + auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tMinOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(8) + auto tmp1 = SAFETRANSLATE(opt_distinct_); + auto tmp2 = SAFETRANSLATE(expr_); + auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); + auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tMaxOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(9) + auto tmp1 = SAFETRANSLATE(opt_distinct_); + auto tmp2 = SAFETRANSLATE(expr_); + auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); + auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tSumOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(10) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tStdOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(11) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tStddevSampOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(12) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tVarianceOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(13) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tVarSampOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + CASESTART(14) + auto tmp1 = SAFETRANSLATE(opt_distinct_); + auto tmp2 = SAFETRANSLATE(expr_list_); + auto tmp3 = SAFETRANSLATE(opt_order_clause_); + auto tmp4 = SAFETRANSLATE(opt_gconcat_separator_); + auto tmp5 = SAFETRANSLATE(opt_windowing_clause_); + auto tmp6 = new IR(IRTYPE::kAggregateFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp4, tmp5); + auto tmp7 = new IR(IRTYPE::kAggregateFunctionTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); + auto tmp8 = new IR(IRTYPE::kAggregateFunctionTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp7); + res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tGroupConcatOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp8); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void AggregateFunction::deep_delete() { + SAFEDELETE(opt_windowing_clause_); + SAFEDELETE(expr_); + SAFEDELETE(opt_distinct_); + SAFEDELETE(expr_list_); + SAFEDELETE(opt_gconcat_separator_); + SAFEDELETE(opt_order_clause_); + delete this; +} + +IR* OptGconcatSeparator::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptGconcatSeparator, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(sconst_); + res = new IR(IRTYPE::kOptGconcatSeparator, OP3(TERMINAL::tSeparator, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptGconcatSeparator::deep_delete() { + SAFEDELETE(sconst_); + delete this; +} + +IR* OptDistinct::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptDistinct, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kOptDistinct, OP3(TERMINAL::tDistinct, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptDistinct::deep_delete() { + delete this; +} + +IR* OptWindowingClause::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptWindowingClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(windowing_clause_); + res = new IR(IRTYPE::kOptWindowingClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptWindowingClause::deep_delete() { + SAFEDELETE(windowing_clause_); + delete this; +} + +IR* WindowingClause::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(window_name_or_spec_); + res = new IR(IRTYPE::kWindowingClause, OP3(TERMINAL::tOver, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void WindowingClause::deep_delete() { + SAFEDELETE(window_name_or_spec_); + delete this; +} + +IR* WindowNameOrSpec::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(window_name_); + res = new IR(IRTYPE::kWindowNameOrSpec, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(window_spec_); + res = new IR(IRTYPE::kWindowNameOrSpec, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WindowNameOrSpec::deep_delete() { + SAFEDELETE(window_name_); + SAFEDELETE(window_spec_); + delete this; +} + +IR* ControlFunction::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + auto tmp3 = SAFETRANSLATE(expr_3_); + auto tmp4 = new IR(IRTYPE::kControlFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); + res = new IR(IRTYPE::kControlFunction, OP3(TERMINAL::tIfOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kControlFunction, OP3(TERMINAL::tIfnullOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kControlFunction, OP3(TERMINAL::tNullifOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ControlFunction::deep_delete() { + SAFEDELETE(expr_1_); + SAFEDELETE(expr_2_); + SAFEDELETE(expr_3_); + delete this; +} + +IR* CaseExpr::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(opt_expr_); + auto tmp2 = SAFETRANSLATE(when_clasue_list_); + auto tmp3 = SAFETRANSLATE(opt_else_); + auto tmp4 = new IR(IRTYPE::kCaseExprTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEnd), tmp2, tmp3); + res = new IR(IRTYPE::kCaseExpr, OP3(TERMINAL::tCase, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); + + TRANSLATEEND +} + +void CaseExpr::deep_delete() { + SAFEDELETE(opt_else_); + SAFEDELETE(when_clasue_list_); + SAFEDELETE(opt_expr_); + delete this; +} + +IR* WhenClasueList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(when_list_); + res = new IR(IRTYPE::kWhenClasueList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(when_list_); + auto tmp2 = SAFETRANSLATE(when_clasue_list_); + res = new IR(IRTYPE::kWhenClasueList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void WhenClasueList::deep_delete() { + SAFEDELETE(when_list_); + SAFEDELETE(when_clasue_list_); + delete this; +} + +IR* WhenList::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(expr_1_); + auto tmp2 = SAFETRANSLATE(expr_2_); + res = new IR(IRTYPE::kWhenList, OP3(TERMINAL::tWhen, TERMINAL::tThen, TERMINAL::tEmpty), tmp1, tmp2); + + TRANSLATEEND +} + +void WhenList::deep_delete() { + SAFEDELETE(expr_1_); + SAFEDELETE(expr_2_); + delete this; +} + +IR* OptExpr::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kOptExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptExpr::deep_delete() { + SAFEDELETE(expr_); + delete this; +} + +IR* OptElse::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptElse, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kOptElse, OP3(TERMINAL::tElse, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptElse::deep_delete() { + SAFEDELETE(expr_); + delete this; +} + +IR* TypeCast::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(cast_type_); + res = new IR(IRTYPE::kTypeCast, OP3(TERMINAL::tCastOpLp, TERMINAL::tAs, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(cast_type_); + res = new IR(IRTYPE::kTypeCast, OP3(TERMINAL::tConvertOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void TypeCast::deep_delete() { + SAFEDELETE(cast_type_); + SAFEDELETE(expr_); + delete this; +} + +IR* CastType::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tBinary, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tChar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tNchar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tSigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(4) + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tUnsigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(5) + auto tmp1 = SAFETRANSLATE(float_options_); + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tDecimal, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(6) + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tReal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(7) + auto tmp1 = SAFETRANSLATE(opt_field_length_); + res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tFloat, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void CastType::deep_delete() { + SAFEDELETE(opt_field_length_); + SAFEDELETE(float_options_); + delete this; +} + +IR* FloatOptions::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kFloatOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(field_length_); + res = new IR(IRTYPE::kFloatOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(precision_); + res = new IR(IRTYPE::kFloatOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void FloatOptions::deep_delete() { + SAFEDELETE(field_length_); + SAFEDELETE(precision_); + delete this; +} + +IR* Precision::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(iconst_1_); + auto tmp2 = SAFETRANSLATE(iconst_2_); + res = new IR(IRTYPE::kPrecision, OP3(TERMINAL::tOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); + + TRANSLATEEND +} + +void Precision::deep_delete() { + SAFEDELETE(iconst_1_); + SAFEDELETE(iconst_2_); + delete this; +} + +IR* OptFieldLength::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kOptFieldLength, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(field_length_); + res = new IR(IRTYPE::kOptFieldLength, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void OptFieldLength::deep_delete() { + SAFEDELETE(field_length_); + delete this; +} + +IR* FieldLength::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(iconst_); + res = new IR(IRTYPE::kFieldLength, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void FieldLength::deep_delete() { + SAFEDELETE(iconst_); + delete this; +} + +IR* Literal::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tNull, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tFalse, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tTrue, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Literal::deep_delete() { + delete this; +} + +IR* Columnref::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(column_name_); + res = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(table_name_); + auto tmp2 = SAFETRANSLATE(column_name_); + res = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tOpDot, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void Columnref::deep_delete() { + SAFEDELETE(column_name_); + SAFEDELETE(table_name_); + delete this; +} + +IR* CompOp::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpEqual, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(1) + res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpGreatereq, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(2) + res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpGreaterthan, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(3) + res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpLesseq, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(4) + res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpLessthan, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + CASESTART(5) + res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpNotequal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void CompOp::deep_delete() { + delete this; +} + +IR* AllSubquery::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kAllSubquery, OP3(TERMINAL::tAll, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kAllSubquery, OP3(TERMINAL::tAny, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(2) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kAllSubquery, OP3(TERMINAL::tSome, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void AllSubquery::deep_delete() { + SAFEDELETE(subquery_); + delete this; +} + +IR* InSubquery::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kInSubquery, OP3(TERMINAL::tIn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(subquery_); + res = new IR(IRTYPE::kInSubquery, OP3(TERMINAL::tNotIn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void InSubquery::deep_delete() { + SAFEDELETE(subquery_); + delete this; +} + +IR* ExprList::translate() { + TRANSLATESTART + + SWITCHSTART + CASESTART(0) + auto tmp1 = SAFETRANSLATE(expr_); + res = new IR(IRTYPE::kExprList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + CASEEND + CASESTART(1) + auto tmp1 = SAFETRANSLATE(expr_); + auto tmp2 = SAFETRANSLATE(expr_list_); + res = new IR(IRTYPE::kExprList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); + CASEEND + SWITCHEND + + TRANSLATEEND +} + +void ExprList::deep_delete() { + SAFEDELETE(expr_); + SAFEDELETE(expr_list_); + delete this; +} + +IR* Iconst::translate(){ + TRANSLATESTART + + res = new IR(kIconst, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + res->long_val_ = this->long_val_; + + TRANSLATEEND +} + +void Iconst::deep_delete(){ + delete this; +} + +IR* Fconst::translate(){ + TRANSLATESTART + + res = new IR(kFconst, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + res->float_val_ = this->float_val_; + + TRANSLATEEND +} + +void Fconst::deep_delete(){ + delete this; +} + +IR* Sconst::translate(){ + TRANSLATESTART + + res = new IR(kSconst, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + res->str_val_ = this->str_val_; + + TRANSLATEEND +} + +void Sconst::deep_delete(){ + delete this; +} + +IR* Ident::translate(){ + TRANSLATESTART + + res = new IR(kIdent, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + res->str_val_ = this->str_val_; + + TRANSLATEEND +} + +void Ident::deep_delete(){ + delete this; +} + +IR* Alias::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kAlias, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void Alias::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + +IR* ColumnName::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kColumnName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void ColumnName::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + +IR* WindowName::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kWindowName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void WindowName::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + +IR* TableName::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kTableName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void TableName::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + +IR* ConstraintName::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kConstraintName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void ConstraintName::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + +IR* IndexName::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kIndexName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void IndexName::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + +IR* ViewName::translate() { + TRANSLATESTART + + auto tmp1 = SAFETRANSLATE(ident_); + res = new IR(IRTYPE::kViewName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); + + TRANSLATEEND +} + +void ViewName::deep_delete() { + SAFEDELETE(ident_); + delete this; +} + diff --git a/src/connector.cpp b/src/connector.cpp new file mode 100755 index 0000000..6ee4746 --- /dev/null +++ b/src/connector.cpp @@ -0,0 +1,177 @@ +#include "../include/connector.h" + +static void myproc(void* arg, const PGresult* res) { + return; +} + +Connector::Connector(const char* host, const char* userName, const char* password, unsigned int port, const char* serverName) { + conninfo_ += "host=" + string(host) + " "; + conninfo_ += "user=" + string(userName) + " "; + conninfo_ += "password=" + string(password) + " "; + conninfo_ += "port=" + to_string(port); + + serverName_ = serverName; + + return; +} + +bool Connector::start_db(const char* file, char* const options[]) { + pid_t dbPid = get_pid_by_name(); + + if (dbPid != 1) { + SQLSTATUS status = reset_db(); + + if (status == SQLSTATUS::ssNormal) { + return true; + } + + return false; + } + + int i = 0; + while (dbPid == 1 && i < 10) { + pid_t pid = fork(); + + if (pid == 0) { + execvp(file, options); + exit(1); + } + else { + wait(NULL); + sleep(5); + } + + dbPid = get_pid_by_name(); + i++; + } + + if (dbPid != 1) { + SQLSTATUS status = reset_db(); + + if (status == SQLSTATUS::ssNormal) { + return true; + } + } + + return false; +} +bool Connector::close_db() { + pid_t dbPid = get_pid_by_name(); + int res = -1; + + if (dbPid != 1) { + res = kill(dbPid, SIGKILL); + } + + if (res == -1) { + return false; + } + + sleep(5); + + return true; +} + +SQLSTATUS Connector::execute(const char* sql) { + SQLSTATUS res = SQLSTATUS::ssNormal; + string curConninfo = "dbname=test " + conninfo_; + + PGconn* conn = PQconnectdb(curConninfo.c_str()); + if (PQstatus(conn) != CONNECTION_OK) { + PQfinish(conn); + return SQLSTATUS::ssConnectFailed; + } + + PQsetNoticeReceiver(conn, myproc, nullptr); + + reset_database(conn); + + PGresult* pgres = PQexec(conn, sql); + if (PQstatus(conn) != CONNECTION_OK) { + res = SQLSTATUS::ssServerCrash; + } + else if (PQresultStatus(pgres) != PGRES_COMMAND_OK && PQresultStatus(pgres) != PGRES_TUPLES_OK) { + res = SQLSTATUS::ssSemanticError; + } + + PQclear(pgres); + PQfinish(conn); + + return res; +} + +void Connector::reset_database(PGconn* conn) { + PGresult* res = PQexec(conn, "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"); + PQclear(res); + + return; +} + +SQLSTATUS Connector::reset_db() { + SQLSTATUS res = SQLSTATUS::ssNormal; + string curConninfo = "dbname=postgres " + conninfo_; + + PGconn* conn = PQconnectdb(curConninfo.c_str()); + if (PQstatus(conn) != CONNECTION_OK) { + PQfinish(conn); + return SQLSTATUS::ssConnectFailed; + } + + PQsetNoticeReceiver(conn, myproc, nullptr); + + int i = 0; + + PGresult* pgres = PQexec(conn, "DROP DATABASE IF EXISTS test;"); + PQclear(pgres); + pgres = PQexec(conn, "CREATE DATABASE IF NOT EXISTS test;"); + PQclear(pgres); + + PQfinish(conn); + + res = execute("SELECT 1;"); + + return res; +} + +pid_t Connector::get_pid_by_name() { + DIR* dir; + struct dirent* ptr; + FILE* fp; + char filepath[50]; + char cur_task_name[50]; + char buf[BUF_SIZE]; + + pid_t pid = 1; + + dir = opendir("/proc"); + if (NULL != dir) + { + while ((ptr = readdir(dir)) != NULL) + { + + if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) + continue; + if (DT_DIR != ptr->d_type) + continue; + + sprintf(filepath, "/proc/%s/status", ptr->d_name); + fp = fopen(filepath, "r"); + if (NULL != fp) + { + if (fgets(buf, BUF_SIZE - 1, fp) == NULL) { + fclose(fp); + continue; + } + sscanf(buf, "%*s %s", cur_task_name); + + if (!strcmp(serverName_.c_str(), cur_task_name)) { + sscanf(ptr->d_name, "%d", &pid); + } + fclose(fp); + } + } + closedir(dir); + } + + return pid; +} diff --git a/src/instantiate.cpp b/src/instantiate.cpp new file mode 100755 index 0000000..f1f80cf --- /dev/null +++ b/src/instantiate.cpp @@ -0,0 +1,3555 @@ +#include "../include/instantiate.h" + +using namespace std; + +vector> Column::compatibility_ = {}; +map Column::typeTranslation_ = { + {TERMINAL::tInt, ColumnType::ctInt}, + {TERMINAL::tTinyint, ColumnType::ctTinyInt}, + {TERMINAL::tSmallint, ColumnType::ctSmallInt}, + {TERMINAL::tMediumint, ColumnType::ctMediumInt}, + {TERMINAL::tBigint, ColumnType::ctBigInt}, + {TERMINAL::tReal, ColumnType::ctReal}, + {TERMINAL::tDouble, ColumnType::ctDouble}, + {TERMINAL::tFloat, ColumnType::ctFloat}, + {TERMINAL::tDecimal, ColumnType::ctDecimal}, + {TERMINAL::tNumeric, ColumnType::ctNumeric}, + {TERMINAL::tFixed, ColumnType::ctFixed}, + + {TERMINAL::tBool, ColumnType::ctBool}, + {TERMINAL::tBoolean, ColumnType::ctBoolean}, + + {TERMINAL::tChar, ColumnType::ctChar}, + {TERMINAL::tBinary, ColumnType::ctBinary}, + {TERMINAL::tVarchar, ColumnType::ctVarchar}, + {TERMINAL::tVarbinary, ColumnType::ctVarbinary}, + {TERMINAL::tLongVarbinary, ColumnType::ctLongVarbinary}, + {TERMINAL::tTinyblob, ColumnType::ctTinyBlob}, + {TERMINAL::tMediumblob, ColumnType::ctMediumBlob}, + {TERMINAL::tLongblob, ColumnType::ctLongBlob}, + {TERMINAL::tBlob, ColumnType::ctBlob}, + {TERMINAL::tTinytext, ColumnType::ctTinyText}, + {TERMINAL::tMediumtext, ColumnType::ctMediumText}, + {TERMINAL::tLongtext, ColumnType::ctLongText}, + {TERMINAL::tText, ColumnType::ctText} +}; +map Column::typeToBasicType_ = { + {ColumnType::ctNull, ColumnBasicType::ctBool}, + + {ColumnType::ctInt, ColumnBasicType::ctNumber}, + {ColumnType::ctTinyInt, ColumnBasicType::ctNumber}, + {ColumnType::ctSmallInt, ColumnBasicType::ctNumber}, + {ColumnType::ctMediumInt, ColumnBasicType::ctNumber}, + {ColumnType::ctBigInt, ColumnBasicType::ctNumber}, + {ColumnType::ctReal, ColumnBasicType::ctNumber}, + {ColumnType::ctDouble, ColumnBasicType::ctNumber}, + {ColumnType::ctFloat, ColumnBasicType::ctNumber}, + {ColumnType::ctDecimal, ColumnBasicType::ctNumber}, + {ColumnType::ctNumeric, ColumnBasicType::ctNumber}, + {ColumnType::ctFixed, ColumnBasicType::ctNumber}, + + {ColumnType::ctBool, ColumnBasicType::ctBool}, + {ColumnType::ctBoolean, ColumnBasicType::ctBool}, + + {ColumnType::ctChar, ColumnBasicType::ctString}, + {ColumnType::ctBinary, ColumnBasicType::ctString}, + {ColumnType::ctVarchar, ColumnBasicType::ctString}, + {ColumnType::ctVarbinary, ColumnBasicType::ctString}, + {ColumnType::ctLongVarbinary, ColumnBasicType::ctString}, + {ColumnType::ctTinyBlob, ColumnBasicType::ctString}, + {ColumnType::ctMediumBlob, ColumnBasicType::ctString}, + {ColumnType::ctLongBlob, ColumnBasicType::ctString}, + {ColumnType::ctBlob, ColumnBasicType::ctString}, + {ColumnType::ctTinyText, ColumnBasicType::ctString}, + {ColumnType::ctMediumText, ColumnBasicType::ctString}, + {ColumnType::ctLongText, ColumnBasicType::ctString}, + {ColumnType::ctText, ColumnBasicType::ctString} +}; + +Instantiator::Instantiator() { + random_device rd; + srand(rd()); + + IRTrim_ = new IRTrim(this); + exprInstantiator_ = new ExprInstantiator(this); + globalStatusManger_ = new GlobalStatusManger(); + + startTime = chrono::steady_clock::now(); + + return; +} +Instantiator::~Instantiator() { + delete IRTrim_; + delete globalStatusManger_; + delete exprInstantiator_; + + return; +} + +unsigned int Instantiator::get_duration_ms(){ + chrono::time_point curTime = chrono::steady_clock::now(); + + return chrono::duration_cast(curTime - startTime).count(); +} + +bool Instantiator::instantaite_sql(IR* root) { + int maxCapacity = calc_capacity(root); + int curCapacity = calc_node(root); + + if (curCapacity > maxCapacity) { + return false; + } + + instantiate_parse_toplevel(NT_check(root, IRTYPE::kParseToplevel)); + + return true; +} +int Instantiator::calc_capacity(IR* root) { + int tmp_node_upper_limit = 0; + + unsigned int curCapacity = CAPACITYBASE * pow(CAPACITYGROWTHRATE, static_cast(get_duration_ms() / TIMETHRESHOLD)); + curCapacity = curCapacity > MAXCAPACITY ? MAXCAPACITY : curCapacity; + + if (root->type_ != IRTYPE::kParseToplevel) + return 0; + + IR* stmtmulti = root->left_; + + while (stmtmulti) { + tmp_node_upper_limit += curCapacity; + stmtmulti = stmtmulti->right_; + } + + return tmp_node_upper_limit; +} +int Instantiator::calc_node(IR* root) { + int res = 0; + + if (root->left_) res += calc_node(root->left_); + if (root->right_) res += calc_node(root->right_); + + return res + 1; +} + +void Instantiator::instantiate_parse_toplevel(IR* parse_toplevel) { + assert(parse_toplevel != nullptr && parse_toplevel->type_ == IRTYPE::kParseToplevel); + IR* stmtmulti = NT_check(parse_toplevel->left_, IRTYPE::kStmtmulti); + + while (stmtmulti != nullptr) { + IR* stmt = NT_check(stmtmulti->left_, IRTYPE::kStmt); + + switch (stmt->left_->type_) { + case IRTYPE::kSelectStmt: { + instantiate_select_stmt(NT_check(stmt->left_, IRTYPE::kSelectStmt)); + break; + } + case IRTYPE::kCreateTableStmt: { + instantiate_create_table_stmt(NT_check(stmt->left_, IRTYPE::kCreateTableStmt)); + break; + } + case IRTYPE::kCreateViewStmt: { + instantiate_create_view_stmt(NT_check(stmt->left_, IRTYPE::kCreateViewStmt)); + break; + } + case IRTYPE::kCreateIndexStmt: { + instantiate_create_index_stmt(NT_check(stmt->left_, IRTYPE::kCreateIndexStmt)); + break; + } + case IRTYPE::kDropIndexStmt: { + instantiate_drop_index_stmt(NT_check(stmt->left_, IRTYPE::kDropIndexStmt)); + break; + } + case IRTYPE::kDropTableStmt: { + instantiate_drop_table_or_view_stmt(NT_check(stmt->left_, IRTYPE::kDropTableStmt), IdentifierType::iTable); + break; + } + case IRTYPE::kDropViewStmt: { + instantiate_drop_table_or_view_stmt(NT_check(stmt->left_, IRTYPE::kDropViewStmt), IdentifierType::iView); + break; + } + case IRTYPE::kDeleteStmt: { + instantiate_delete_stmt(NT_check(stmt->left_, IRTYPE::kDeleteStmt)); + break; + } + case IRTYPE::kUpdateStmt: { + instantiate_update_stmt(NT_check(stmt->left_, IRTYPE::kUpdateStmt)); + break; + } + case IRTYPE::kInsertStmt: { + instantiate_insert_stmt(NT_check(stmt->left_, IRTYPE::kInsertStmt)); + break; + } + case IRTYPE::kAlterTableStmt: { + instantiate_alter_table_stmt(NT_check(stmt->left_, IRTYPE::kAlterTableStmt)); + break; + } + default: { + return; + } + } + + stmtmulti = stmtmulti->right_; + } + + globalStatusManger_->reset_status(); + + return; +} + +void Instantiator::instantiate_alter_table_stmt(IR* alter_table_stmt) { + IR* table_name = NT_check(alter_table_stmt->left_, IRTYPE::kTableName); + IR* alter_list = NT_check(alter_table_stmt->right_, IRTYPE::kAlterList); + + vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); + if (tables.empty()) { + return; + } + + Table* table = tables[rand() % tables.size()]; + instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); + + IR* curNode = alter_list; + while (curNode != nullptr) { + IR* alter_list_item = NT_check(curNode->left_, IRTYPE::kAlterListItem); + instantiate_alter_list_item(alter_list_item, table); + + curNode = curNode->right_; + } + + return; +} +void Instantiator::instantiate_alter_list_item(IR* alter_list_item, Table* table) { + switch (alter_list_item->op_->prefix_) { + case TERMINAL::tAddColumn: { + IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); + IR* field_def = NT_check(alter_list_item->right_->left_, IRTYPE::kFieldDef); + IR* opt_place = NT_check(alter_list_item->right_->right_, IRTYPE::kOptPlace); + + IR* data_type = NT_check(field_def->left_, IRTYPE::kDataType); + IR* opt_column_attribute_list = NT_check(field_def->right_, IRTYPE::kOptColumnAttributeList); + + ColumnType type = instantiate_data_type(data_type); + + name_t newColumnName = table->get_acce_column_name(); + Column* column = new Column(newColumnName, type); + + instantiate_ident(column_name, IdentifierType::iColumn, newColumnName); + + if (opt_place->left_ != nullptr) { + IR* tmp_column_name = NT_check(opt_place->left_, IRTYPE::kColumnName); + + Column* tmp_column = table->columns_[rand() % table->columns_.size()]; + instantiate_ident(tmp_column_name, IdentifierType::iColumn, tmp_column->identifierName_); + + table->add_column(column, tmp_column); + } + else if(opt_place->op_->prefix_ == TERMINAL::tFirst) { + table->add_column_first(column); + } + else { + table->add_column(column); + } + + if (opt_column_attribute_list->left_ != nullptr) { + IR* curNode = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); + + while (curNode != nullptr) { + IR* column_attribute = NT_check(curNode->left_, IRTYPE::kColumnAttribute); + instantiate_column_attribute(column_attribute, column, table); + + curNode = curNode->right_; + } + } + + break; + } + case TERMINAL::tAddColumnOpLp: { + IR* table_element_list = NT_check(alter_list_item->left_, IRTYPE::kTableElementList); + + instantiate_table_element_list(table_element_list, table); + + break; + } + case TERMINAL::tAdd: { + IR* table_constraint_def = NT_check(alter_list_item->left_, IRTYPE::kTableConstraintDef); + + if (table_constraint_def->op_->prefix_ == TERMINAL::tIndex) { + instantiate_table_constraint_def_index(table_constraint_def, table); + } + else if (table_constraint_def->op_->middle_ == tForeignKey) { + instantiate_table_constraint_def_foreign_key(table_constraint_def, table); + } + else if (table_constraint_def->right_->type_ == IRTYPE::kCheckConstraint) { + instantiate_table_constraint_def_check(table_constraint_def, table); + } + else { + instantiate_table_constraint_def_key(table_constraint_def, table); + } + + break; + } + case TERMINAL::tChangeColumn: { + IR* column_name_1 = nullptr; + IR* column_name_2 = nullptr; + IR* field_def = nullptr; + IR* opt_place = nullptr; + + IR* unknown = nullptr; + + column_name_1 = NT_check(alter_list_item->left_, IRTYPE::kColumnName); + unknown = alter_list_item->right_; + + column_name_2 = NT_check(unknown->left_, IRTYPE::kColumnName); + unknown = unknown->right_; + + field_def = NT_check(unknown->left_, IRTYPE::kFieldDef); + opt_place = NT_check(unknown->right_, IRTYPE::kOptPlace); + + IR* data_type = NT_check(field_def->left_, IRTYPE::kDataType); + IR* opt_column_attribute_list = NT_check(field_def->right_, IRTYPE::kOptColumnAttributeList); + + Column* column = table->columns_[rand() % table->columns_.size()]; + column->columnType_ = instantiate_data_type(data_type); + + name_t newColumnName = table->get_acce_column_name(); + instantiate_ident(column_name_1, IdentifierType::iColumn, column->identifierName_); + instantiate_ident(column_name_2, IdentifierType::iColumn, newColumnName); + + table->column_rename(column, column->identifierName_, newColumnName); + + if (opt_place->left_ != nullptr) { + IR* tmp_column_name = NT_check(opt_place->left_, IRTYPE::kColumnName); + + Column* tmp_column = table->columns_[rand() % table->columns_.size()]; + + if (tmp_column != column) { + instantiate_ident(tmp_column_name, IdentifierType::iColumn, tmp_column->identifierName_); + table->move_column(column, tmp_column); + } + else { + deep_delete(opt_place->left_); + opt_place->left_ = nullptr; + opt_place->op_->prefix_ = TERMINAL::tEmpty; + } + } + else if (opt_place->op_->prefix_ == TERMINAL::tFirst) { + table->move_column_first(column); + } + + if (opt_column_attribute_list->left_ != nullptr) { + IR* curNode = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); + + while (curNode != nullptr) { + IR* column_attribute = NT_check(curNode->left_, IRTYPE::kColumnAttribute); + instantiate_column_attribute(column_attribute, column, table); + + curNode = curNode->right_; + } + } + + break; + } + case TERMINAL::tModifyColumn: { + IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); + IR* field_def = NT_check(alter_list_item->right_->left_, IRTYPE::kFieldDef); + IR* opt_place = NT_check(alter_list_item->right_->right_, IRTYPE::kOptPlace); + + IR* data_type = NT_check(field_def->left_, IRTYPE::kDataType); + IR* opt_column_attribute_list = NT_check(field_def->right_, IRTYPE::kOptColumnAttributeList); + + Column* column = table->columns_[rand() % table->columns_.size()]; + column->columnType_ = instantiate_data_type(data_type); + instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); + + if (opt_place->left_ != nullptr) { + IR* tmp_column_name = NT_check(opt_place->left_, IRTYPE::kColumnName); + + Column* tmp_column = table->columns_[rand() % table->columns_.size()]; + + if (tmp_column != column) { + instantiate_ident(tmp_column_name, IdentifierType::iColumn, tmp_column->identifierName_); + table->move_column(column, tmp_column); + } + else { + deep_delete(opt_place->left_); + opt_place->left_ = nullptr; + opt_place->op_->prefix_ = TERMINAL::tEmpty; + } + } + else if (opt_place->op_->prefix_ == TERMINAL::tFirst) { + table->move_column_first(column); + } + + if (opt_column_attribute_list->left_ != nullptr) { + IR* curNode = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); + + while (curNode != nullptr) { + IR* column_attribute = NT_check(curNode->left_, IRTYPE::kColumnAttribute); + instantiate_column_attribute(column_attribute, column, table); + + curNode = curNode->right_; + } + } + + break; + } + case TERMINAL::tDropColumn: { + IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); + + if (table->columns_.size() <= 1) { + return; + } + + Column* column = table->columns_[rand() % table->columns_.size()]; + instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); + + table->drop_column(column); + + break; + } + case TERMINAL::tDropForeignKey: { + IR* constraint_name = NT_check(alter_list_item->left_, IRTYPE::kConstraintName); + + Constraint* constraint = nullptr; + for (Constraint* c : table->constraints_) { + if (c->constraintType_ != ConstraintType::ctForeignKey) { + continue; + } + + constraint = c; + break; + } + + if (constraint == nullptr) { + return; + } + + instantiate_ident(constraint_name, IdentifierType::iConstraint, constraint->identifierName_); + + table->drop_constraint(constraint); + + break; + } + case TERMINAL::tDropPrimaryKey: { + if (table->hasPrimaryKey_ == false) { + return; + } + + Constraint* constraint = nullptr; + for (Constraint* c : table->constraints_) { + if (c->constraintType_ != ConstraintType::ctPrimaryKey) { + continue; + } + + constraint = c; + break; + } + + assert(constraint != nullptr); + + table->drop_constraint(constraint); + table->hasPrimaryKey_ = false; + + break; + } + case TERMINAL::tDropIndex: { + IR* index_name = NT_check(alter_list_item->left_, IRTYPE::kIndexName); + + if (table->indexes_.empty()) { + return; + } + + Index* index = table->indexes_[rand() % table->indexes_.size()]; + instantiate_ident(index_name, IdentifierType::iIndex, index->identifierName_); + + table->drop_index(index); + + break; + } + case TERMINAL::tDropCheck: { + IR* constraint_name = NT_check(alter_list_item->left_, IRTYPE::kConstraintName); + + Constraint* constraint = nullptr; + for (Constraint* c : table->constraints_) { + if (c->constraintType_ != ConstraintType::ctCheck) { + continue; + } + + constraint = c; + break; + } + + if (constraint == nullptr) { + return; + } + + instantiate_ident(constraint_name, IdentifierType::iConstraint, constraint->identifierName_); + + table->drop_constraint(constraint); + + break; + } + case TERMINAL::tDropConstraint: { + IR* constraint_name = NT_check(alter_list_item->left_, IRTYPE::kConstraintName); + + if (table->constraints_.empty()) { + return; + } + + Constraint* constraint = table->constraints_[rand() % table->constraints_.size()]; + instantiate_ident(constraint_name, IdentifierType::iConstraint, constraint->identifierName_); + + table->drop_constraint(constraint); + + break; + } + case TERMINAL::tAlterColumn: { + IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); + + Column* column = table->columns_[rand() % table->columns_.size()]; + instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); + + switch (alter_list_item->op_->middle_) { + case TERMINAL::tSetDefaultOpLp: { + IR* expr_root = NT_check(alter_list_item->right_, IRTYPE::kExprRoot); + + exprInstantiator_->instantiate_expr_root(expr_root, table->columns_, StmtLocation::slNotSubquery); + + break; + } + case TERMINAL::tDropDefault: { + break; + } + case TERMINAL::tSet: { + break; + } + default: { + fprintf(stderr, "ERROR: Unknown ALTER COLUMN!!!\n"); + assert(0); + } + } + + break; + } + case TERMINAL::tAlterIndex: { + IR* index_name = NT_check(alter_list_item->left_, IRTYPE::kIndexName); + + if (table->indexes_.empty()) { + return; + } + + Index* index = table->indexes_[rand() % table->indexes_.size()]; + instantiate_ident(index_name, IdentifierType::iIndex, index->identifierName_); + + break; + } + case TERMINAL::tRenameTo: { + IR* table_name = NT_check(alter_list_item->left_, IRTYPE::kTableName); + + name_t newTableName = globalStatusManger_->get_new_table_name(); + + instantiate_ident(table_name, IdentifierType::iTable, newTableName); + + table->identifierName_ = newTableName; + + break; + } + case TERMINAL::tRenameIndex: { + IR* index_name_1 = NT_check(alter_list_item->left_, IRTYPE::kIndexName); + IR* index_name_2 = NT_check(alter_list_item->right_, IRTYPE::kIndexName); + + if (table->indexes_.empty()) { + return; + } + + Index* index = table->indexes_[rand() % table->indexes_.size()]; + name_t newIndexName = globalStatusManger_->get_new_index_name(); + + instantiate_ident(index_name_1, IdentifierType::iIndex, index->identifierName_); + instantiate_ident(index_name_2, IdentifierType::iIndex, newIndexName); + + index->identifierName_ = newIndexName; + + break; + } + case TERMINAL::tRenameColumn: { + IR* column_name_1 = NT_check(alter_list_item->left_, IRTYPE::kColumnName); + IR* column_name_2 = NT_check(alter_list_item->right_, IRTYPE::kColumnName); + + Column* column = table->columns_[rand() % table->columns_.size()]; + name_t newColumnName = table->get_acce_column_name(); + + instantiate_ident(column_name_1, IdentifierType::iColumn, column->identifierName_); + instantiate_ident(column_name_2, IdentifierType::iColumn, newColumnName); + + table->column_rename(column, column->identifierName_, newColumnName); + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown alter_list_item!!!\n"); + assert(0); + } + } + + return; +} + +void Instantiator::instantiate_insert_stmt(IR* insert_stmt) { + IR* table_name = nullptr; + IR* insert_from_constructor = nullptr; + IR* opt_values_reference = nullptr; + IR* opt_insert_update_list = nullptr; + IR* update_list = nullptr; + IR* insert_query_expression = nullptr; + + IR* unknown = insert_stmt->right_->right_; + + table_name = NT_check(unknown->left_, IRTYPE::kTableName); + unknown = unknown->right_; + + switch (unknown->left_->type_) { + case IRTYPE::kInsertFromConstructor: { + insert_from_constructor = NT_check(unknown->left_, IRTYPE::kInsertFromConstructor); + unknown = unknown->right_; + + opt_values_reference = NT_check(unknown->left_, IRTYPE::kOptValuesReference); + + break; + } + case IRTYPE::kUpdateList: { + update_list = NT_check(unknown->left_, IRTYPE::kUpdateList); + unknown = unknown->right_; + + opt_values_reference = NT_check(unknown->left_, IRTYPE::kOptValuesReference); + + break; + } + case IRTYPE::kInsertQueryExpression: { + insert_query_expression = NT_check(unknown->left_, IRTYPE::kInsertQueryExpression); + break; + } + default: { + fprintf(stderr, "ERROR: Unknown Insert Stmt!!!\n"); + assert(0); + } + } + + opt_insert_update_list = NT_check(unknown->right_, IRTYPE::kOptInsertUpdateList); + + vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); + if (tables.empty()) { + return; + } + + globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + Table* chosenTable = tables[rand() % tables.size()]; + instantiate_ident(table_name, IdentifierType::iTable, chosenTable->identifierName_); + + Table* newTable = new Table(chosenTable, info); + info->add_used_table(newTable); + + int chosenColumnNumber = chosenTable->columns_.size(); + Table* tmpTable = nullptr; + + info->update_acceColumns(); + + if (insert_from_constructor != nullptr) { + bool hasOptColumn = false; + + IR* values_list = nullptr; + IR* column_list = nullptr; + + if (insert_from_constructor->right_ == nullptr) { + values_list = NT_check(insert_from_constructor->left_, IRTYPE::kValuesList); + } + else { + values_list = NT_check(insert_from_constructor->right_, IRTYPE::kValuesList); + column_list = NT_check(insert_from_constructor->left_, IRTYPE::kColumnList); + } + + if (column_list != nullptr) { + hasOptColumn = true; + + vector columnsSeq = chosenTable->get_column_seq(); + vector chosenColumns = vector(columnsSeq.begin(), columnsSeq.begin() + exprInstantiator_->get_random_integer(1, chosenTable->columns_.size())); + + chosenColumnNumber = chosenColumns.size(); + + instantiate_column_list(column_list, chosenColumns); + } + + int tmpChosenColumnNumber = chosenColumnNumber; + if (hasOptColumn == false) { + tmpChosenColumnNumber = (rand() % 20) == 0 ? 0 : chosenColumnNumber; + chosenColumnNumber = tmpChosenColumnNumber; + } + + instantiate_values_list(values_list, tmpChosenColumnNumber); + } + else if (update_list != nullptr) { + chosenColumnNumber = instantiate_update_list(update_list, nullptr); + } + else { + IR* query_expression = nullptr; + IR* column_list = nullptr; + + if (insert_query_expression->right_ == nullptr) { + query_expression = NT_check(insert_query_expression->left_, IRTYPE::kQueryExpression); + } + else { + query_expression = NT_check(insert_query_expression->right_, IRTYPE::kQueryExpression); + column_list = NT_check(insert_query_expression->left_, IRTYPE::kColumnList); + } + + if (column_list != nullptr) { + vector columnsSeq = chosenTable->get_column_seq(); + vector chosenColumns = vector(columnsSeq.begin(), columnsSeq.begin() + exprInstantiator_->get_random_integer(1, chosenTable->columns_.size())); + + chosenColumnNumber = chosenColumns.size(); + + instantiate_column_list(column_list, chosenColumns); + } + + Table* tmp = instantiate_query_expression(query_expression, StmtLocation::slNotSubquery, DEFAULTROWNUMBER, chosenColumnNumber); + delete tmp; + } + + if (opt_values_reference != nullptr && opt_values_reference->left_ != nullptr) { + if (chosenColumnNumber != 0) { + IR* tmp_table_name = NT_check(opt_values_reference->left_, IRTYPE::kTableName); + IR* opt_column_list = NT_check(opt_values_reference->right_, IRTYPE::kOptColumnList); + + name_t newTableName = globalStatusManger_->get_new_table_name(); + instantiate_ident(tmp_table_name, IdentifierType::iTable, newTableName); + + vector chosenColumns; + if (opt_insert_update_list->left_ != nullptr) { + tmpTable = new Table(newTableName, IdentifierType::iTable, info); + + for (int i = 0; i < chosenColumnNumber; i++) { + name_t newColumnName = tmpTable->get_acce_column_name(); + Column* newColumn = new Column(newColumnName, ColumnType::ctNull); + + tmpTable->add_column(newColumn); + chosenColumns.push_back(newColumnName); + } + + if (opt_column_list->left_ == nullptr) { + opt_column_list->left_ = deep_copy(IRTrim_->simple_column_list_); + opt_column_list->op_->prefix_ = TERMINAL::tOpLp; + opt_column_list->op_->middle_ = TERMINAL::tOpRp; + } + } + else { + for (int i = 0; i < chosenColumnNumber; i++) { + chosenColumns.push_back(static_cast(i)); + } + } + + if (opt_column_list->left_ != nullptr) { + IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); + instantiate_column_list(column_list, chosenColumns); + } + } + else { + deep_delete(opt_values_reference->left_); + deep_delete(opt_values_reference->right_); + + opt_values_reference->left_ = nullptr; + opt_values_reference->right_ = nullptr; + + opt_values_reference->op_->prefix_ = TERMINAL::tEmpty; + } + } + + if (opt_insert_update_list->left_ != nullptr) { + IR* tmp_update_list = NT_check(opt_insert_update_list->left_, IRTYPE::kUpdateList); + instantiate_update_list(tmp_update_list, tmpTable); + } + + if (tmpTable != nullptr) { + delete tmpTable; + } + + globalStatusManger_->pop_selectInfo(); + + return; +} +void Instantiator::instantiate_values_list(IR* values_list, int chosenColumnNumber) { + IR* curNode = values_list; + while (curNode != nullptr) { + IR* opt_values = NT_check(curNode->left_->left_, IRTYPE::kOptValues); + IR* values = opt_values->left_ == nullptr ? nullptr : NT_check(opt_values->left_, IRTYPE::kValues); + + if (chosenColumnNumber == 0 && values != nullptr) { + deep_delete(opt_values->left_); + opt_values->left_ = nullptr; + values = nullptr; + } + else if (chosenColumnNumber != 0 && values == nullptr) { + opt_values->left_ = deep_copy(IRTrim_->simple_values_); + values = opt_values->left_; + } + + if (values != nullptr) { + assert(chosenColumnNumber > 0); + instantiate_values(values, chosenColumnNumber); + } + + curNode = curNode->right_; + } + + return; +} +void Instantiator::instantiate_values(IR* values, int chosenColumnNumber) { + int count = 0; + IR* curNode = values; + while (curNode != nullptr) { + IR* expr_or_default = NT_check(curNode->left_, IRTYPE::kExprOrDefault); + IR* expr_root = expr_or_default->left_ == nullptr ? nullptr : NT_check(expr_or_default->left_, IRTYPE::kExprRoot); + + if (expr_root != nullptr) { + vector tmp; + exprInstantiator_->instantiate_expr_root(expr_root, tmp, StmtLocation::slNotSubquery); + } + + count++; + + if (count == chosenColumnNumber && curNode->right_ != nullptr) { + deep_delete(curNode->right_); + + curNode->right_ = nullptr; + curNode->op_->middle_ = TERMINAL::tEmpty; + } + else if (count < chosenColumnNumber && curNode->right_ == nullptr) { + curNode->right_ = deep_copy(IRTrim_->simple_values_); + curNode->op_->middle_ = TERMINAL::tOpComma; + } + + curNode = curNode->right_; + } + + return; +} + +void Instantiator::instantiate_update_stmt(IR* update_stmt) { + IR* opt_with_clause = nullptr; + IR* table_reference_list = nullptr; + IR* update_list = nullptr; + IR* opt_where_clause = nullptr; + IR* opt_order_clause = nullptr; + IR* opt_simple_limit = nullptr; + + IR* unknown = nullptr; + + opt_with_clause = NT_check(update_stmt->left_, IRTYPE::kOptWithClause); + unknown = update_stmt->right_->right_->right_; + + table_reference_list = NT_check(unknown->left_, IRTYPE::kTableReferenceList); + unknown = unknown->right_; + + update_list = NT_check(unknown->left_, IRTYPE::kUpdateList); + unknown = unknown->right_; + + opt_where_clause = NT_check(unknown->left_, IRTYPE::kOptWhereClause); + unknown = unknown->right_; + + opt_order_clause = NT_check(unknown->left_, IRTYPE::kOptOrderClause); + opt_simple_limit = NT_check(unknown->right_, IRTYPE::kOptSimpleLimit); + + globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (opt_with_clause->left_ != nullptr) { + IR* with_clause = NT_check(opt_with_clause->left_, IRTYPE::kWithClause); + instantiate_with_clause(with_clause); + } + + IR* curNode = table_reference_list; + while (curNode != nullptr) { + IR* table_reference = NT_check(curNode->left_, IRTYPE::kTableReference); + instantiate_table_reference(table_reference); + + curNode = curNode->right_; + } + + info->update_acceColumns(); + + if (opt_where_clause->left_ != nullptr) { + IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); + instantiate_where_clause(where_clause); + } + + if (opt_order_clause->left_ != nullptr) { + IR* order_clause = NT_check(opt_order_clause->left_, IRTYPE::kOrderClause); + instantiate_order_clause(order_clause); + } + + if (opt_simple_limit->left_ != nullptr) { + IR* iconst = NT_check(opt_simple_limit->left_, IRTYPE::kIconst); + iconst->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); + } + + instantiate_update_list(update_list, nullptr); + + globalStatusManger_->pop_selectInfo(); + + return; +} +int Instantiator::instantiate_update_list(IR* update_list, Table* table) { + int chosenColumnNumber = 0; + + vector columns; + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (info->acceColumns_.empty()) { + return 0; + } + + if (table != nullptr) { + vector tmp = vector(COLUMNNAMEMAX, 0); + + for (Column* c : table->columns_) { + tmp[c->identifierName_]++; + } + + for (Column* c : info->acceColumns_) { + Column* tmpColumn = new Column(c); + tmpColumn->parentTable_ = c->parentTable_; + + if (tmp[tmpColumn->identifierName_] != 0) { + tmpColumn->duplicated_ = ColumnStatus::csDuplication; + } + + tmp[tmpColumn->identifierName_]++; + columns.push_back(tmpColumn); + } + + for (Column* c : table->columns_) { + Column* tmpColumn = new Column(c); + tmpColumn->parentTable_ = c->parentTable_; + + if (tmp[tmpColumn->identifierName_] > 1) { + tmpColumn->duplicated_ = ColumnStatus::csDuplication; + } + + columns.push_back(tmpColumn); + } + } + + IR* curNode = update_list; + while (curNode != nullptr) { + chosenColumnNumber++; + + IR* columnref = NT_check(curNode->left_->left_, IRTYPE::kColumnref); + IR* expr_root = (curNode->left_->right_->left_ == nullptr) ? nullptr : NT_check(curNode->left_->right_->left_, IRTYPE::kExprRoot); + + Column* chosenColumn = info->acceColumns_[rand() % info->acceColumns_.size()]; + + IR* column_name = nullptr; + IR* table_name = nullptr; + + if (chosenColumn->duplicated_ == ColumnStatus::csDuplication && columnref->right_ == nullptr) { + IR* tmp1 = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* tmp2 = new IR(IRTYPE::kTableName, OP0(), tmp1, nullptr); + + columnref->right_ = columnref->left_; + columnref->left_ = tmp2; + columnref->op_->middle_ = TERMINAL::tOpDot; + } + + if (columnref->right_ != nullptr) { + table_name = NT_check(columnref->left_, IRTYPE::kTableName); + column_name = NT_check(columnref->right_, IRTYPE::kColumnName); + } + else { + column_name = NT_check(columnref->left_, IRTYPE::kColumnName); + } + + instantiate_ident(column_name, IdentifierType::iColumn, chosenColumn->identifierName_); + if (table_name != nullptr) { + instantiate_ident(table_name, IdentifierType::iTable, chosenColumn->parentTable_->identifierName_); + } + + if (expr_root != nullptr) { + if (table != nullptr) { + exprInstantiator_->instantiate_expr_root(expr_root, columns, StmtLocation::slNotSubquery); + } + else { + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slNotSubquery); + } + } + + curNode = curNode->right_; + } + + for (Column* c : columns) { + delete c; + } + + return chosenColumnNumber; +} + +void Instantiator::instantiate_delete_stmt(IR* delete_stmt) { + IR* opt_with_clause = nullptr; + IR* table_name = nullptr; + IR* opt_alias = nullptr; + IR* opt_where_clause = nullptr; + IR* opt_order_clause = nullptr; + IR* opt_simple_limit = nullptr; + IR* table_list = nullptr; + IR* table_reference_list = nullptr; + + IR* unknown = nullptr; + + opt_with_clause = NT_check(delete_stmt->left_, IRTYPE::kOptWithClause); + unknown = delete_stmt->right_->right_; + + if (unknown->left_->type_ == IRTYPE::kTableName) { + table_name = NT_check(unknown->left_, IRTYPE::kTableName); + unknown = unknown->right_; + + opt_alias = NT_check(unknown->left_, IRTYPE::kOptAlias); + unknown = unknown->right_; + + opt_where_clause = NT_check(unknown->left_, IRTYPE::kOptWhereClause); + unknown = unknown->right_; + + opt_order_clause = NT_check(unknown->left_, IRTYPE::kOptOrderClause); + opt_simple_limit = NT_check(unknown->right_, IRTYPE::kOptSimpleLimit); + } + else { + table_list = NT_check(unknown->left_, IRTYPE::kTableList); + unknown = unknown->right_; + + table_reference_list = NT_check(unknown->left_, IRTYPE::kTableReferenceList); + opt_where_clause = NT_check(unknown->right_, IRTYPE::kOptWhereClause); + } + + globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (table_name != nullptr) { + if (opt_with_clause->left_ != nullptr) { + deep_delete(opt_with_clause->left_); + opt_with_clause->left_ = nullptr; + } + + vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); + if (tables.empty()) { + globalStatusManger_->pop_selectInfo(); + return; + } + + Table* chosenTable = tables[rand() % tables.size()]; + Table* newTable = new Table(chosenTable, info); + info->add_used_table(newTable); + + instantiate_ident(table_name, IdentifierType::iTable, newTable->identifierName_); + + if (opt_alias->left_ != nullptr) { + IR* alias = NT_check(opt_alias->left_, IRTYPE::kAlias); + name_t newName = globalStatusManger_->get_new_table_name(); + + instantiate_ident(alias, IdentifierType::iTable, newName); + + newTable->identifierName_ = newName; + } + + info->update_acceColumns(); + + if (opt_where_clause->left_ != nullptr) { + IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); + instantiate_where_clause(where_clause); + } + + if (opt_order_clause->left_ != nullptr) { + IR* order_clause = NT_check(opt_order_clause->left_, IRTYPE::kOrderClause); + instantiate_order_clause(order_clause); + } + + if (opt_simple_limit->left_ != nullptr) { + IR* iconst = NT_check(opt_simple_limit->left_, IRTYPE::kIconst); + iconst->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); + } + } + else if (table_list != nullptr) { + if (opt_with_clause->left_ != nullptr) { + IR* with_clause = NT_check(opt_with_clause->left_, IRTYPE::kWithClause); + instantiate_with_clause(with_clause); + } + + IR* curNode = table_reference_list; + while (curNode != nullptr) { + IR* table_reference = NT_check(curNode->left_, IRTYPE::kTableReference); + instantiate_table_reference(table_reference); + + curNode = curNode->right_; + } + + info->update_acceColumns(); + + vector tables = info->usedTables_; + assert(!tables.empty()); + + curNode = table_list; + while (curNode != nullptr) { + IR* table_name = NT_check(curNode->left_, IRTYPE::kTableName); + + int tmp = rand() % tables.size(); + Table* table = tables[tmp]; + tables.erase(tables.begin() + tmp); + + instantiate_ident(table_name, table->identifierType_, table->identifierName_); + + if (tables.empty() && curNode->right_ != nullptr) { + deep_delete(curNode->right_); + curNode->right_ = nullptr; + curNode->op_->middle_ = TERMINAL::tEmpty; + } + + curNode = curNode->right_; + } + + if (opt_where_clause->left_ != nullptr) { + IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); + instantiate_where_clause(where_clause); + } + } + else { + fprintf(stderr, "ERROR: Incorrect Delete Statement!!!\n"); + assert(0); + } + + globalStatusManger_->pop_selectInfo(); + + return; +} + +void Instantiator::instantiate_drop_table_or_view_stmt(IR* drop_table_stmt, IdentifierType type) { + bool existFlag = false; + + IR* if_exists = NT_check(drop_table_stmt->left_, IRTYPE::kIfExists); + IR* table_list = NT_check(drop_table_stmt->right_, IRTYPE::kTableList); + + vector tables = globalStatusManger_->get_acce_table(type); + if (tables.empty()) { + if_exists->op_->prefix_ = TERMINAL::tIfExists; + } + + if (if_exists->op_->prefix_ == TERMINAL::tIfExists) { + existFlag = true; + } + + name_t nextTableName = UNREFERENCE; + if (type == IdentifierType::iTable) { + nextTableName = globalStatusManger_->get_new_table_name(); + } + else if (type == IdentifierType::iView) { + nextTableName = globalStatusManger_->get_new_view_name(); + } + else { + fprintf(stderr, "ERROR: IdentifierType isn't iTable or iView!!!\n"); + assert(0); + } + + IR* curNode = table_list; + while (curNode != nullptr) { + name_t tmpTableName = UNREFERENCE; + IR* table_name = NT_check(curNode->left_, IRTYPE::kTableName); + + if (existFlag == true && (rand() % 2 == 0 || tables.empty())) { + tmpTableName = exprInstantiator_->get_random_integer(nextTableName, UCHAR_MAX); + } + else { + int tmp = rand() % tables.size(); + Table* tmpTable = tables[tmp]; + + tmpTableName = tmpTable->identifierName_; + + tables.erase(tables.begin() + tmp); + globalStatusManger_->drop_table(tmpTable); + } + + instantiate_ident(table_name, type, tmpTableName); + + if (existFlag == false && tables.empty() && curNode->right_ != nullptr) { + deep_delete(curNode->right_); + curNode->right_ = nullptr; + curNode->op_->middle_ = TERMINAL::tEmpty; + } + + curNode = curNode->right_; + } + + return; +} + +void Instantiator::instantiate_drop_index_stmt(IR* drop_index_stmt) { + IR* index_name = NT_check(drop_index_stmt->left_, IRTYPE::kIndexName); + IR* table_name = NT_check(drop_index_stmt->right_, IRTYPE::kTableName); + + vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); + if (tables.empty()) { + return; + } + + Table* table = nullptr; + for (Table* t : tables) { + if (t->indexes_.empty()) { + continue; + } + + table = t; + break; + } + + if (table == nullptr) { + return; + } + + Index* index = table->indexes_[rand() % table->indexes_.size()]; + + instantiate_ident(index_name, IdentifierType::iIndex, index->identifierName_); + instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); + + table->drop_index(index); + + return; +} + +void Instantiator::instantiate_create_index_stmt(IR* create_index_stmt) { + IR* index_name = nullptr; + IR* table_name = nullptr; + IR* key_list_with_expression = nullptr; + + IR* unknown = create_index_stmt->right_; + + index_name = NT_check(unknown->left_, IRTYPE::kIndexName); + unknown = unknown->right_; + + table_name = NT_check(unknown->left_, IRTYPE::kTableName); + key_list_with_expression = NT_check(unknown->right_, IRTYPE::kKeyListWithExpression); + + vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); + if (tables.empty()) { + return; + } + + Table* table = tables[rand() % tables.size()]; + + name_t newIndexName = globalStatusManger_->get_new_index_name(); + Index* newIndex = new Index(newIndexName); + + instantiate_ident(index_name, IdentifierType::iIndex, newIndex->identifierName_); + instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); + + newIndex->columns_ = instantiate_key_list_with_expression(key_list_with_expression, table, ConstraintType::ctNull); + + table->add_index(newIndex); + + return; +} + +void Instantiator::instantiate_create_view_stmt(IR* create_view_stmt) { + IR* opt_or_replace = nullptr; + IR* view_name = nullptr; + IR* opt_column_list = nullptr; + IR* query_expression = nullptr; + + IR* unknown = nullptr; + + opt_or_replace = NT_check(create_view_stmt->left_, IRTYPE::kOptOrReplace); + unknown = create_view_stmt->right_->right_; + + view_name = NT_check(unknown->left_, IRTYPE::kViewName); + unknown = unknown->right_; + + opt_column_list = NT_check(unknown->left_, IRTYPE::kOptColumnList); + query_expression = NT_check(unknown->right_, IRTYPE::kQueryExpression); + + name_t newViewName = globalStatusManger_->get_new_view_name(); + if (opt_or_replace->op_->prefix_ == TERMINAL::tOrReplace) { + newViewName = (newViewName != 0 && (rand() % 2) == 0) ? (rand() % newViewName) : newViewName; + globalStatusManger_->drop_table(newViewName, IdentifierType::iView); + } + + instantiate_ident(view_name, IdentifierType::iView, newViewName); + + Table* view = instantiate_query_expression(query_expression, StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + + view->identifierName_ = newViewName; + view->identifierType_ = IdentifierType::iView; + + if (opt_column_list->left_ != nullptr) { + IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); + + for (Column* column : view->columns_) { + view->column_rename(column, column->identifierName_, view->get_acce_column_name()); + } + + instantiate_column_list(column_list, view->columns_); + } + + assert(globalStatusManger_->add_table(view)); + + return; +} + +void Instantiator::instantiate_create_table_stmt(IR* create_table_stmt) { + Table* res = nullptr; + + IR* opt_temporary = nullptr; + IR* opt_if_not_exists = nullptr; + IR* table_name = nullptr; + IR* table_element_list = nullptr; + IR* duplicate_as_qe = nullptr; + IR* opt_duplicate_as_qe = nullptr; + + IR* unknown = nullptr; + + opt_temporary = NT_check(create_table_stmt->left_, IRTYPE::kOptTemporary); + unknown = create_table_stmt->right_; + + opt_if_not_exists = NT_check(unknown->left_, IRTYPE::kOptIfNotExists); + unknown = unknown->right_; + + table_name = NT_check(unknown->left_, IRTYPE::kTableName); + unknown = unknown->right_; + + if (unknown->type_ == IRTYPE::kDuplicateAsQe) { + duplicate_as_qe = NT_check(unknown, IRTYPE::kDuplicateAsQe); + } + else { + table_element_list = NT_check(unknown->left_, IRTYPE::kTableElementList); + opt_duplicate_as_qe = NT_check(unknown->right_, IRTYPE::kOptDuplicateAsQe); + + if (opt_duplicate_as_qe->left_ != nullptr) { + duplicate_as_qe = NT_check(opt_duplicate_as_qe->left_, IRTYPE::kDuplicateAsQe); + } + } + + name_t newTableName = globalStatusManger_->get_new_table_name(); + instantiate_ident(table_name, IdentifierType::iTable, newTableName); + + if (table_element_list != nullptr) { + res = new Table(newTableName, IdentifierType::iTable, nullptr); + instantiate_table_element_list(table_element_list, res); + } + + if (duplicate_as_qe != nullptr) { + IR* query_expression = nullptr; + + if (duplicate_as_qe->left_->type_ == IRTYPE::kQueryExpression) { + query_expression = NT_check(duplicate_as_qe->left_, IRTYPE::kQueryExpression); + } + else { + query_expression = NT_check(duplicate_as_qe->right_, IRTYPE::kQueryExpression); + } + + Table* tmpTable = instantiate_query_expression(query_expression, StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + + if (res == nullptr) { + res = tmpTable; + } + else { + for (Column* c : tmpTable->columns_) { + res->add_column(new Column(c), nullptr); + } + + delete tmpTable; + } + + res->identifierName_ = newTableName; + } + + if (opt_temporary->op_->prefix_ == TERMINAL::tTemporary) { + res->isTemporary_ = true; + } + + assert(globalStatusManger_->add_table(res)); + + return; +} +void Instantiator::instantiate_table_element_list(IR* table_element_list, Table* table) { + map> columnWithColumnAttributes; + + int column_def_count = 0; + IR* curNode = table_element_list; + while (curNode != nullptr) { + IR* table_element = NT_check(curNode->left_, IRTYPE::kTableElement); + + if (table_element->left_->type_ == IRTYPE::kColumnDef) { + column_def_count++; + } + + curNode = curNode->right_; + } + + if (table->columns_.empty() && column_def_count == 0) { + deep_delete(table_element_list->left_); + table_element_list->left_ = deep_copy(IRTrim_->simple_table_element_); + } + + curNode = table_element_list; + vector tableConstraintDefs; + while (curNode != nullptr) { + IR* table_element = curNode->left_; + + if (table_element->left_->type_ == IRTYPE::kColumnDef) { + pair> tmp = instantiate_column_def(NT_check(table_element->left_, IRTYPE::kColumnDef), table); + columnWithColumnAttributes[tmp.first] = tmp.second; + } + else { + tableConstraintDefs.push_back(NT_check(table_element->left_, IRTYPE::kTableConstraintDef)); + } + + curNode = curNode->right_; + } + + assert(!table->columns_.empty()); + + for (auto& it : columnWithColumnAttributes) { + for (IR* column_attribute : it.second) { + instantiate_column_attribute(column_attribute, it.first, table); + } + } + + vector waitForDelete; + for (IR* tmp : tableConstraintDefs) { + bool flag = false; + + if (tmp->left_->type_ == IRTYPE::kOptIndexName) { + flag = instantiate_table_constraint_def_index(tmp, table); + } + else if (tmp->right_->type_ == IRTYPE::kCheckConstraint) { + flag = instantiate_table_constraint_def_check(tmp, table); + } + else if (tmp->op_->middle_ == TERMINAL::tForeignKey) { + flag = instantiate_table_constraint_def_foreign_key(tmp, table); + } + else { + flag = instantiate_table_constraint_def_key(tmp, table); + } + + if (flag == false) { + waitForDelete.push_back(tmp); + } + } + + curNode = table_element_list; + IR* preNode = curNode; + while (curNode != nullptr && !waitForDelete.empty()) { + IR* table_element = curNode->left_; + + auto it = find(waitForDelete.begin(), waitForDelete.end(), table_element->left_); + if (it != waitForDelete.end()) { + if (curNode->right_ == nullptr) { + deep_delete(preNode->right_); + preNode->right_ = nullptr; + preNode->op_->middle_ = TERMINAL::tEmpty; + + curNode = preNode; + + waitForDelete.erase(it); + } + else { + IR* tmp = curNode->right_; + + deep_delete(curNode->left_); + curNode->left_ = tmp->left_; + curNode->right_ = tmp->right_; + curNode->op_->middle_ = tmp->op_->middle_; + + tmp->left_ = nullptr; + tmp->right_ = nullptr; + deep_delete(tmp); + + waitForDelete.erase(it); + + continue; + } + } + + preNode = curNode; + curNode = curNode->right_; + } + + assert(waitForDelete.empty()); + + return; +} +pair> Instantiator::instantiate_column_def(IR* column_def, Table* table) { + vector res; + + IR* column_name = NT_check(column_def->left_, IRTYPE::kColumnName); + IR* data_type = NT_check(column_def->right_->left_, IRTYPE::kDataType); + IR* opt_column_attribute_list = NT_check(column_def->right_->right_, IRTYPE::kOptColumnAttributeList); + + name_t columnName = table->get_acce_column_name(); + ColumnType type = instantiate_data_type(data_type); + + Column* column = new Column(columnName, type); + instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); + + if (opt_column_attribute_list->left_ != nullptr) { + IR* column_attribute_list = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); + + while (column_attribute_list != nullptr) { + res.push_back(NT_check(column_attribute_list->left_, IRTYPE::kColumnAttribute)); + column_attribute_list = column_attribute_list->right_; + } + } + + table->add_column(column); + + return { column, res }; +} +ColumnType Instantiator::instantiate_data_type(IR* data_type) { + ColumnType res = ColumnType::ctNull; + + switch (data_type->left_->type_) { + case IRTYPE::kNumberType: { + IR* number_type = NT_check(data_type->left_, IRTYPE::kNumberType); + + IR* type = number_type->left_; + IR* precision = nullptr; + IR* float_options = nullptr; + + if (type->type_ == IRTYPE::kRealType) { + IR* opt_precision = NT_check(number_type->right_->left_, IRTYPE::kOptPrecision); + precision = (opt_precision->left_ == nullptr) ? nullptr : NT_check(opt_precision->left_, IRTYPE::kPrecision); + } + else if (type->type_ == IRTYPE::kNumericType) { + float_options = NT_check(number_type->right_->left_, IRTYPE::kFloatOptions); + } + + res = Column::typeTranslation_[type->op_->prefix_]; + + if (float_options != nullptr && float_options->left_ != nullptr) { + if (float_options->left_->type_ == IRTYPE::kPrecision) { + precision = NT_check(float_options->left_, IRTYPE::kPrecision); + } + else { + IR* field_length = NT_check(float_options->left_, IRTYPE::kFieldLength); + IR* iconst = NT_check(field_length->left_, IRTYPE::kIconst); + + int v1 = exprInstantiator_->get_random_integer(0, 53); + iconst->long_val_ = v1; + } + } + + if (precision != nullptr) { + IR* iconst_1 = NT_check(precision->left_, IRTYPE::kIconst); + IR* iconst_2 = NT_check(precision->right_, IRTYPE::kIconst); + + int v1 = exprInstantiator_->get_random_integer(1, 255); + int v2 = exprInstantiator_->get_random_float(0, min(v1, 30)); + + iconst_1->long_val_ = v1; + iconst_2->long_val_ = v2; + } + + break; + } + case IRTYPE::kBoolType: { + res = Column::typeTranslation_[data_type->left_->op_->prefix_]; + break; + } + case IRTYPE::kStringType: { + IR* string_type = NT_check(data_type->left_, IRTYPE::kStringType); + + IR* field_length = nullptr; + if (string_type->left_ != nullptr) { + field_length = (string_type->left_->type_ == IRTYPE::kFieldLength) ? NT_check(string_type->left_, IRTYPE::kFieldLength) : string_type->left_->left_; + } + + res = Column::typeTranslation_[string_type->op_->prefix_]; + + if (field_length != nullptr) { + IR* iconst = NT_check(field_length->left_, IRTYPE::kIconst); + + int v1 = exprInstantiator_->get_random_integer(32, 255); + iconst->long_val_ = v1; + } + + break; + } + default: { + fprintf(stderr, "Unknown Data Type!!!\n"); + assert(0); + } + } + + return res; +} +void Instantiator::instantiate_column_attribute(IR* column_attribute, Column* column, Table* table) { + switch (column_attribute->left_->type_) { + case IRTYPE::kNotNull: { + column->notNull_ = true; + break; + } + case IRTYPE::kDefaultAttribute: { + IR* expr_root = NT_check(column_attribute->left_->left_, IRTYPE::kExprRoot); + exprInstantiator_->instantiate_expr_root(expr_root, table->columns_, StmtLocation::slNotSubquery); + + column->hasDefault_ = true; + + break; + } + case IRTYPE::kVisibility: { + column->isVisible_ = (column_attribute->left_->op_->prefix_ == TERMINAL::tVisible) ? true : false; + break; + } + default: { + fprintf(stderr, "Unknown Column Attribute!!!\n"); + assert(0); + } + } + + return; +} +map Instantiator::instantiate_key_list_with_expression(IR* key_list_with_expression, Table* table, ConstraintType type) { + map res; + + IR* curNode = key_list_with_expression; + while (curNode != nullptr) { + IR* key_part_with_expression = NT_check(curNode->left_, IRTYPE::kKeyPartWithExpression); + + if (type == ConstraintType::ctPrimaryKey && key_part_with_expression->left_->type_ != IRTYPE::kKeyPart) { + deep_delete(key_part_with_expression->left_); + key_part_with_expression->left_ = deep_copy(IRTrim_->simple_key_part_); + } + + if (key_part_with_expression->left_->type_ == IRTYPE::kKeyPart) { + IR* key_part = NT_check(key_part_with_expression->left_, IRTYPE::kKeyPart); + IR* iconst = nullptr; + + Column* columnChosen = table->get_column(); + instantiate_ident(NT_check(key_part->left_, IRTYPE::kColumnName), IdentifierType::iColumn, columnChosen->identifierName_); + + if (res.find(columnChosen) == res.end()) { + res[columnChosen] = IndexType::itNormal; + } + + if (key_part->right_->type_ != IRTYPE::kOptOrderingDirection) { + if (Column::typeToBasicType_[columnChosen->columnType_] != ColumnBasicType::ctString) { + deep_delete(key_part->right_); + key_part->right_ = new IR(IRTYPE::kOptOrderingDirection, OP0(), nullptr, nullptr); + } + else { + iconst = NT_check(key_part->right_->left_, IRTYPE::kIconst); + } + } + + if (iconst != nullptr) { + int v1 = exprInstantiator_->get_random_integer(1, 32); + iconst->long_val_ = v1; + } + } + else { + IR* expr_root = NT_check(key_part_with_expression->left_, IRTYPE::kExprRoot); + exprInstantiator_->instantiate_expr_root(expr_root, table->columns_, StmtLocation::slNotSubquery); + + for (Column* column : exprInstantiator_->usedColumnsBuffer_) { + res[column] = IndexType::itFunctional; + } + } + + curNode = curNode->right_; + } + + return res; +} +bool Instantiator::instantiate_table_constraint_def_index(IR* table_constraint_def, Table* table) { + IR* opt_index_name = NT_check(table_constraint_def->left_, IRTYPE::kOptIndexName); + IR* key_list_with_expression = NT_check(table_constraint_def->right_, IRTYPE::kKeyListWithExpression); + + if (opt_index_name->left_ == nullptr) { + opt_index_name->left_ = deep_copy(IRTrim_->simple_index_name_); + } + + name_t newIndexName = globalStatusManger_->get_new_index_name(); + Index* newIndex = new Index(newIndexName); + instantiate_ident(NT_check(opt_index_name->left_, IRTYPE::kIndexName), IdentifierType::iIndex, newIndex->identifierName_); + + newIndex->columns_ = instantiate_key_list_with_expression(key_list_with_expression, table, ConstraintType::ctNull); + + table->add_index(newIndex); + + return true; +} +bool Instantiator::instantiate_table_constraint_def_key(IR* table_constraint_def, Table* table) { + ConstraintType type = ConstraintType::ctNull; + + IR* opt_constraint_name = nullptr; + IR* constraint_key_type = nullptr; + IR* opt_index_name = nullptr; + IR* key_list_with_expression = nullptr; + + IR* unknown = nullptr; + + opt_constraint_name = NT_check(table_constraint_def->left_, IRTYPE::kOptConstraintName); + unknown = table_constraint_def->right_; + + constraint_key_type = NT_check(unknown->left_, IRTYPE::kConstraintKeyType); + unknown = unknown->right_; + + opt_index_name = NT_check(unknown->left_, IRTYPE::kOptIndexName); + key_list_with_expression = NT_check(unknown->right_, IRTYPE::kKeyListWithExpression); + + if (opt_constraint_name->left_ == nullptr) { + opt_constraint_name->left_ = deep_copy(IRTrim_->simple_constraint_name_); + opt_constraint_name->op_->prefix_ = TERMINAL::tConstraint; + } + + if (opt_index_name->left_ == nullptr) { + opt_index_name->left_ = deep_copy(IRTrim_->simple_index_name_); + } + + if (table->hasPrimaryKey_ == true) { + if (constraint_key_type->op_->prefix_ == TERMINAL::tPrimaryKey); { + return false; + } + + type = ConstraintType::ctUnique; + } + else { + type = (constraint_key_type->op_->prefix_ == TERMINAL::tPrimaryKey) ? ConstraintType::ctPrimaryKey : ConstraintType::ctUnique; + if (type == ConstraintType::ctPrimaryKey) { + table->hasPrimaryKey_ = true; + } + } + + name_t newConstraintName = globalStatusManger_->get_new_constraint_name(); + name_t newIndexName = globalStatusManger_->get_new_index_name(); + + Constraint* newConstraint = new Constraint(newConstraintName, type); + Index* newIndex = new Index(newIndexName); + + instantiate_ident(NT_check(opt_constraint_name->left_, IRTYPE::kConstraintName), IdentifierType::iConstraint, newConstraint->identifierName_); + instantiate_ident(NT_check(opt_index_name->left_, IRTYPE::kIndexName), IdentifierType::iIndex, newIndex->identifierName_); + + newConstraint->columns_ = instantiate_key_list_with_expression(key_list_with_expression, table, type); + newIndex->columns_ = newConstraint->columns_; + + table->add_constraint(newConstraint, newIndex); + + return true; +} +bool Instantiator::instantiate_table_constraint_def_check(IR* table_constraint_def, Table* table) { + IR* opt_constraint_name = NT_check(table_constraint_def->left_, IRTYPE::kOptConstraintName); + IR* check_constraint = NT_check(table_constraint_def->right_, IRTYPE::kCheckConstraint); + + if (opt_constraint_name->left_ == nullptr) { + opt_constraint_name->left_ = deep_copy(IRTrim_->simple_constraint_name_); + opt_constraint_name->op_->prefix_ = TERMINAL::tConstraint; + } + + name_t newConstraintName = globalStatusManger_->get_new_constraint_name(); + Constraint* newConstraint = new Constraint(newConstraintName, ConstraintType::ctCheck); + instantiate_ident(NT_check(opt_constraint_name->left_, IRTYPE::kConstraintName), IdentifierType::iConstraint, newConstraint->identifierName_); + + exprInstantiator_->instantiate_expr_root(NT_check(check_constraint->left_, IRTYPE::kExprRoot), table->columns_, StmtLocation::slNotSubquery); + for (Column* column : exprInstantiator_->usedColumnsBuffer_) { + newConstraint->columns_[column] = IndexType::itFunctional; + } + + table->add_constraint(newConstraint); + + return true; +} +bool Instantiator::instantiate_table_constraint_def_foreign_key(IR* table_constraint_def, Table* table) { + IR* opt_constraint_name = nullptr; + IR* opt_index_name = nullptr; + IR* key_list = nullptr; + IR* references = nullptr; + IR* table_name = nullptr; + IR* column_list = nullptr; + + IR* unknown = nullptr; + + opt_constraint_name = NT_check(table_constraint_def->left_, IRTYPE::kOptConstraintName); + unknown = table_constraint_def->right_; + + opt_index_name = NT_check(unknown->left_, IRTYPE::kOptIndexName); + unknown = unknown->right_; + + key_list = NT_check(unknown->left_, IRTYPE::kKeyList); + references = NT_check(unknown->right_, IRTYPE::kReferences); + + table_name = NT_check(references->left_, IRTYPE::kTableName); + column_list = NT_check(references->right_->left_, IRTYPE::kColumnList); + + vector curTableColumn; + vector otherTableColumn; + if (check_foreign_key(table, curTableColumn, otherTableColumn) == false) { + return false; + } + + assert(!curTableColumn.empty() && curTableColumn.size() == otherTableColumn.size()); + + if (opt_constraint_name->left_ == nullptr) { + opt_constraint_name->left_ = deep_copy(IRTrim_->simple_constraint_name_); + opt_constraint_name->op_->prefix_ = TERMINAL::tConstraint; + } + + if (opt_index_name->left_ == nullptr) { + opt_index_name->left_ = deep_copy(IRTrim_->simple_index_name_); + } + + name_t newConstraintName = globalStatusManger_->get_new_constraint_name(); + name_t newIndexName = globalStatusManger_->get_new_index_name(); + + Constraint* newConstraint = new Constraint(newConstraintName, ConstraintType::ctForeignKey); + + IR* constraint_name = NT_check(opt_constraint_name->left_, IRTYPE::kConstraintName); + IR* index_name = NT_check(opt_index_name->left_, IRTYPE::kIndexName); + + instantiate_ident(constraint_name, IdentifierType::iConstraint, newConstraint->identifierName_); + instantiate_ident(index_name, IdentifierType::iIndex, newIndexName); + + instantiate_ident(table_name, IdentifierType::iTable, otherTableColumn[0]->parentTable_->identifierName_); + + instantiate_key_list(key_list, curTableColumn); + instantiate_column_list(column_list, otherTableColumn); + + for (int i = 0; i < curTableColumn.size(); i++) { + newConstraint->refToOtherColumns_[curTableColumn[i]].push_back(otherTableColumn[i]); + } + + table->add_constraint(newConstraint); + + return true; +} + +void Instantiator::instantiate_select_stmt(IR* select_stmt) { + globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + + Table* t = instantiate_query_expression(NT_check(select_stmt->left_, IRTYPE::kQueryExpression)); + + globalStatusManger_->pop_selectInfo(); + delete t; + + return; +} +Table* Instantiator::instantiate_query_expression(IR* query_expression, StmtLocation location, int rowNumber, int columnNumber) { + globalStatusManger_->push_selectInfo(location, rowNumber, columnNumber); + + Table* res = instantiate_query_expression(NT_check(query_expression, IRTYPE::kQueryExpression)); + globalStatusManger_->pop_selectInfo(); + + res->inSelectStmtInfo_ = globalStatusManger_->get_cur_selectInfo(); + + return res; +} +Table* Instantiator::instantiate_query_expression(IR* query_expression) { + Table* res = nullptr; + + IR* with_clause = nullptr; + IR* query_expression_body = nullptr; + IR* opt_order_clause = nullptr; + IR* opt_limit_clause = nullptr; + + IR* unknown = nullptr; + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (query_expression->left_->type_ == IRTYPE::kQueryExpressionBody) { + query_expression_body = NT_check(query_expression->left_, IRTYPE::kQueryExpressionBody); + unknown = query_expression->right_; + } + else { + with_clause = NT_check(query_expression->left_, IRTYPE::kWithClause); + + unknown = query_expression->right_; + query_expression_body = NT_check(unknown->left_, IRTYPE::kQueryExpressionBody); + + unknown = unknown->right_; + } + + opt_order_clause = NT_check(unknown->left_, IRTYPE::kOptOrderClause); + opt_limit_clause = NT_check(unknown->right_, IRTYPE::kOptLimitClause); + + if (with_clause != nullptr) { + instantiate_with_clause(with_clause); + } + + switch (query_expression_body->left_->type_) { + case IRTYPE::kQueryPrimary: { + res = instantiate_query_primary(NT_check(query_expression_body->left_, IRTYPE::kQueryPrimary)); + break; + } + case IRTYPE::kQueryExpressionParens: { + IR* query_expression_parens = NT_check(query_expression_body->left_, IRTYPE::kQueryExpressionParens); + while (query_expression_parens->left_->type_ == IRTYPE::kQueryExpressionParens) { + query_expression_parens = NT_check(query_expression_parens->left_, IRTYPE::kQueryExpressionParens); + } + + res = instantiate_query_expression(NT_check(query_expression_parens->left_, IRTYPE::kQueryExpression)); + + break; + } + case IRTYPE::kQueryExpressionBody: { + res = instanitate_union(query_expression_body); + break; + } + default: { + fprintf(stderr, "ERROR: Unknown query_expression_body->left_->type_: %d\n", static_cast(query_expression_body->left_->type_)); + assert(0); + } + } + + assert(info->usedTables_.empty()); + + if (opt_order_clause->left_ != nullptr) { + IR* order_clause = NT_check(opt_order_clause->left_, IRTYPE::kOrderClause); + + vector usedTables = { res }; + vector duplicationInfo = vector(COLUMNNAMEMAX, 0); + info->update_acceColumns(usedTables, duplicationInfo); + + instantiate_order_clause(order_clause); + + info->acceColumns_.clear(); + } + + if (info->has_row_limit() && opt_limit_clause->left_ == nullptr) { + opt_limit_clause->left_ = deep_copy(IRTrim_->simple_limit_); + } + + if (opt_limit_clause->left_ != nullptr) { + IR* limit_clause = NT_check(opt_limit_clause->left_, IRTYPE::kLimitClause); + instantiate_limit_clause(limit_clause); + } + + return res; +} +Table* Instantiator::instantiate_query_primary(IR* query_primary) { + Table* res = nullptr; + + IR* query_specification = nullptr; + + IR* opt_select_options = nullptr; + IR* select_item_list = nullptr; + IR* opt_from_clause = nullptr; + IR* opt_where_clause = nullptr; + IR* opt_group_clause = nullptr; + IR* opt_having_clause = nullptr; + IR* opt_window_clause = nullptr; + + IR* unknown = nullptr; + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + info->clear_local_info(); + + query_specification = NT_check(query_primary->left_, IRTYPE::kQuerySpecification); + + opt_select_options = NT_check(query_specification->left_, IRTYPE::kOptSelectOptions); + unknown = query_specification->right_; + + select_item_list = NT_check(unknown->left_, IRTYPE::kSelectItemList); + unknown = unknown->right_; + + opt_from_clause = NT_check(unknown->left_, IRTYPE::kOptFromClause); + unknown = unknown->right_; + + opt_where_clause = NT_check(unknown->left_, IRTYPE::kOptWhereClause); + unknown = unknown->right_; + + opt_group_clause = NT_check(unknown->left_, IRTYPE::kOptGroupClause); + unknown = unknown->right_; + + opt_having_clause = NT_check(unknown->left_, IRTYPE::kOptHavingClause); + opt_window_clause = NT_check(unknown->right_, IRTYPE::kOptWindowClause); + + if (opt_from_clause->left_) { + int acceTableNumber = globalStatusManger_->get_acce_table_number(); + + if (acceTableNumber == 0) { + deep_delete(opt_from_clause->left_); + opt_from_clause->left_ = nullptr; + } + else { + IR* from_clause = NT_check(opt_from_clause->left_, IRTYPE::kFromClause); + instantiate_from_clause(from_clause); + } + } + + info->update_acceColumns(); + + if (opt_where_clause->left_ != nullptr) { + IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); + instantiate_where_clause(where_clause); + } + + if (opt_having_clause->left_ != nullptr) { + instantiate_having_clause(opt_having_clause); + } + + if (opt_window_clause->left_ != nullptr) { + instantiate_window_clause(opt_window_clause); + } + + res = instantiate_select_item_list(select_item_list); + + if (info->hasAggregate && !info->usedInnerColumns_.empty() && opt_group_clause->left_ == nullptr) { + IR* olap_opt = new IR(IRTYPE::kOlapOpt, OP0(), nullptr, nullptr); + IR* expr_root_list = deep_copy(IRTrim_->simple_expr_root_list_); + + opt_group_clause->left_ = expr_root_list; + opt_group_clause->right_ = olap_opt; + opt_group_clause->op_->prefix_ = TERMINAL::tGroupBy; + } + + if (opt_group_clause->left_ != nullptr) { + instantiate_group_clause(opt_group_clause); + } + + info->clear_local_info(); + + return res; +} +Table* Instantiator::instanitate_union(IR* query_expression_body) { + Table* res = nullptr; + + IR* query_expression_body_1 = nullptr; + IR* query_expression_body_2 = nullptr; + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + StmtLocation oldLocation = info->location_; + + stack stk; + vector queue; + + query_expression_body_1 = NT_check(query_expression_body->left_, IRTYPE::kQueryExpressionBody); + query_expression_body_2 = NT_check(query_expression_body->right_->right_, IRTYPE::kQueryExpressionBody); + + stk.push(query_expression_body_2); + stk.push(query_expression_body_1); + + while (!stk.empty()) { + IR* curIR = stk.top(); + stk.pop(); + + switch (curIR->left_->type_) { + case IRTYPE::kQueryPrimary: { + IR* query_primary = NT_check(curIR->left_, IRTYPE::kQueryPrimary); + queue.push_back(query_primary); + + break; + } + case IRTYPE::kQueryExpressionParens: { + IR* query_expression_parens = NT_check(curIR->left_, IRTYPE::kQueryExpressionParens); + queue.push_back(query_expression_parens); + + break; + } + case IRTYPE::kQueryExpressionBody: { + IR* t_query_expression_body_1 = NT_check(curIR->left_, IRTYPE::kQueryExpressionBody); + IR* t_query_expression_body_2 = NT_check(curIR->right_->right_, IRTYPE::kQueryExpressionBody); + + stk.push(t_query_expression_body_2); + stk.push(t_query_expression_body_1); + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown query_expression_body->left_->type_: %d\n", static_cast(curIR->left_->type_)); + assert(0); + } + } + } + + assert(queue.size() >= 2); + + for (int i = 0; i < queue.size(); i++) { + if (i == 0 && (oldLocation == StmtLocation::slRecursiveCTE || oldLocation == StmtLocation::slRecursivePart1)) { + info->location_ = StmtLocation::slRecursivePart1; + } + else if (i == queue.size() - 1 && (oldLocation == StmtLocation::slRecursiveCTE || oldLocation == StmtLocation::slRecursivePart2)) { + info->location_ = StmtLocation::slRecursivePart2; + } + else if(oldLocation == StmtLocation::slRecursiveCTE || oldLocation == StmtLocation::slRecursivePart1 || oldLocation == StmtLocation::slRecursivePart2) { + info->location_ = StmtLocation::slCTE; + } + + IR* curIR = queue[i]; + Table* tmp = nullptr; + + switch (curIR->type_) { + case IRTYPE::kQueryPrimary: { + tmp = instantiate_query_primary(NT_check(curIR, IRTYPE::kQueryPrimary)); + break; + } + case IRTYPE::kQueryExpressionParens: { + IR* query_expression_parens = NT_check(curIR, IRTYPE::kQueryExpressionParens); + while (query_expression_parens->left_->type_ == IRTYPE::kQueryExpressionParens) { + query_expression_parens = NT_check(query_expression_parens->left_, IRTYPE::kQueryExpressionParens); + } + + tmp = instantiate_query_expression(NT_check(query_expression_parens->left_, IRTYPE::kQueryExpression)); + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); + assert(0); + } + } + + if (i == 0) { + res = tmp; + + if (curIR->type_ == IRTYPE::kQueryPrimary) { + if (!info->has_column_limit()) { + info->columnNumber_ = res->columns_.size(); + } + + if (info->recursiveCteName_ != UNREFERENCE && info->recursiveCte_ == nullptr) { + res->identifierName_ = info->recursiveCteName_; + info->recursiveCte_ = res; + } + } + } + else { + delete tmp; + } + } + + info->location_ = oldLocation; + + return res; +} + +void Instantiator::instantiate_with_clause(IR* with_clause) { + StmtLocation location = StmtLocation::slCTE; + + IR* with_list = NT_check(with_clause->left_, IRTYPE::kWithList); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + info->clear_cte(); + + if (with_clause->op_->prefix_ == TERMINAL::tWithRecursive) { + location = StmtLocation::slRecursiveCTE; + } + + while (with_list != nullptr) { + IR* common_table_expr = NT_check(with_list->left_, IRTYPE::kCommonTableExpr); + + IR* table_name = NT_check(common_table_expr->left_, IRTYPE::kTableName); + IR* opt_column_list = NT_check(common_table_expr->right_->left_, IRTYPE::kOptColumnList); + IR* subquery = NT_check(common_table_expr->right_->right_, IRTYPE::kSubquery); + + name_t tableName = globalStatusManger_->get_new_table_name(); + if (location == StmtLocation::slRecursiveCTE) { + info->recursiveCteName_ = tableName; + } + + info->update_acceColumns(); + + IR* curNode = subquery->left_; + while (curNode->type_ != IRTYPE::kQueryExpression) { + curNode = curNode->left_; + } + + Table* table = instantiate_query_expression(curNode, location, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + table->isSubQuery_ = true; + table->identifierName_ = tableName; + + instantiate_ident(table_name, IdentifierType::iTable, tableName); + + if (opt_column_list->left_) { + IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); + instantiate_column_list(column_list, table->columns_); + } + + info->innerCteTables_.push_back(table); + + info->recursiveCteName_ = UNREFERENCE; + info->acceColumns_.clear(); + + with_list = with_list->right_; + } + + return; +} +void Instantiator::instantiate_order_clause(IR* order_clause) { + IR* order_list = NT_check(order_clause->left_, IRTYPE::kOrderList); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + while (order_list != nullptr) { + IR* expr_root = NT_check(order_list->left_->left_, IRTYPE::kExprRoot); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slOrderClause); + info->add_out_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + order_list = order_list->right_; + } + + return; +} +void Instantiator::instantiate_limit_clause(IR* limit_clause) { + IR* limit_options = NT_check(limit_clause->left_, IRTYPE::kLimitOptions); + IR* iconst_1 = NT_check(limit_options->left_, IRTYPE::kIconst); + IR* iconst_2 = (limit_options->right_ == nullptr) ? nullptr : NT_check(limit_options->right_, IRTYPE::kIconst); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (info->has_row_limit()) { + iconst_1->long_val_ = exprInstantiator_->get_random_integer(info->rowNumber_, info->rowNumber_); + info->rowNumber_ = DEFAULTROWNUMBER; + } + else { + iconst_1->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); + } + + if (iconst_2 != nullptr) { + iconst_2->long_val_ = exprInstantiator_->get_random_integer(OFFSETMIN, OFFSETMAX); + } + + return; +} + +Table* Instantiator::instantiate_select_item_list(IR* select_item_list) { + IR* t_select_item_list = select_item_list; + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + Table* res = new Table(UNREFERENCE, IdentifierType::iTable, info); + + int columnCount = 0; + while (t_select_item_list != nullptr) { + IR* select_item = NT_check(t_select_item_list->left_, IRTYPE::kSelectItem); + + if (info->location_ == StmtLocation::slRecursivePart1 && columnCount == 0) { + deep_delete(select_item->left_); + deep_delete(select_item->right_); + + select_item->left_ = deep_copy(IRTrim_->simple_expr_root_); + select_item->right_ = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), deep_copy(IRTrim_->simple_alias_), nullptr); + + IR* alias = NT_check(select_item->right_->left_, IRTYPE::kAlias); + instantiate_ident(alias, IdentifierType::iColumn, RESERVEDCOLUMNNAME); + + bool tmp = res->add_column(new Column(RESERVEDCOLUMNNAME, ColumnType::ctInt)); + assert(tmp); + + columnCount++; + } + else { + if (select_item->left_->type_ == IRTYPE::kTableWild) { + bool success = false; + + if (!info->usedTables_.empty()) { + IR* table_wild = NT_check(select_item->left_, IRTYPE::kTableWild); + IR* table_name = nullptr; + + if (table_wild->left_ != nullptr) { + table_name = NT_check(table_wild->left_, IRTYPE::kTableName); + } + + if (table_name != nullptr) { + int index = exprInstantiator_->get_random_integer(0, info->usedTables_.size() - 1); + Table* table = info->usedTables_[index]; + + if (!info->exist_duplicated_column(res->columns_, table->columns_) && (!info->has_column_limit() || (columnCount + table->columns_.size()) <= info->columnNumber_)) { + instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); + + for (Column* c : table->columns_) { + bool tmp = res->add_column(new Column(c)); + assert(tmp); + } + + columnCount += table->columns_.size(); + success = true; + } + } + else { + vector columns; + + for (Table* t : info->usedTables_) { + for (Column* c : t->columns_) { + columns.push_back(c); + } + } + + if (!info->exist_duplicated_column(res->columns_, columns) && (!info->has_column_limit() || (columnCount + columns.size()) <= info->columnNumber_)) { + for (Column* c : columns) { + bool tmp = res->add_column(new Column(c)); + assert(tmp); + } + + columnCount += columns.size(); + success = true; + } + } + } + + if (!success) { + deep_delete(select_item->left_); + + select_item->left_ = deep_copy(IRTrim_->simple_expr_root_); + select_item->right_ = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), deep_copy(IRTrim_->simple_alias_), nullptr); + } + } + + if (select_item->left_->type_ == IRTYPE::kExprRoot) { + IR* expr_root = NT_check(select_item->left_, IRTYPE::kExprRoot); + IR* opt_alias = NT_check(select_item->right_, IRTYPE::kOptAlias); + + if (opt_alias->left_ == nullptr) { + opt_alias->left_ = deep_copy(IRTrim_->simple_alias_); + opt_alias->op_->prefix_ = TERMINAL::tAs; + } + + IR* alias = NT_check(opt_alias->left_, IRTYPE::kAlias); + + name_t newColumnName = res->get_acce_column_name(); + instantiate_ident(alias, IdentifierType::iColumn, newColumnName); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slTargetList); + info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + bool tmp = res->add_column(new Column(newColumnName, ColumnType::ctNull)); + assert(tmp); + + columnCount++; + } + } + + if (info->has_column_limit()) { + assert(info->columnNumber_ > 0); + + if (columnCount >= info->columnNumber_ && t_select_item_list->right_ != nullptr) { + deep_delete(t_select_item_list->right_); + + t_select_item_list->right_ = nullptr; + t_select_item_list->op_->middle_ = TERMINAL::tEmpty; + } + else if (columnCount < info->columnNumber_ && t_select_item_list->right_ == nullptr) { + t_select_item_list->right_ = deep_copy(IRTrim_->simple_select_item_list_); + t_select_item_list->op_->middle_ = TERMINAL::tOpComma; + } + } + + t_select_item_list = t_select_item_list->right_; + } + + assert(res->columns_.size() == columnCount); + + return res; +} +void Instantiator::instantiate_from_clause(IR* from_clause) { + IR* table_reference_list = NT_check(from_clause->left_, IRTYPE::kTableReferenceList); + + while (table_reference_list != nullptr) { + IR* table_reference = NT_check(table_reference_list->left_, IRTYPE::kTableReference); + instantiate_table_reference(table_reference); + + table_reference_list = table_reference_list->right_; + } + + return; +} +vector Instantiator::instantiate_table_reference(IR* table_reference) { + vector res; + vector queue; + + if (table_reference->left_->type_ == IRTYPE::kJoinedTable) { + IR* joined_table = NT_check(table_reference->left_, IRTYPE::kJoinedTable); + queue.push_back(joined_table); + } + else { + IR* table_factor = NT_check(table_reference->left_, IRTYPE::kTableFactor); + + switch (table_factor->left_->type_) { + case IRTYPE::kSingleTable: { + IR* single_table = NT_check(table_factor->left_, IRTYPE::kSingleTable); + queue.push_back(single_table); + + break; + } + case IRTYPE::kDerivedTable: { + IR* derived_table = NT_check(table_factor->left_, IRTYPE::kDerivedTable); + queue.push_back(derived_table); + + break; + } + case IRTYPE::kJoinedTableParens: { + IR* joined_table = NT_check(table_factor->left_->left_, IRTYPE::kJoinedTable); + queue.push_back(joined_table); + + break; + } + case IRTYPE::kTableReferenceListParens: { + IR* table_reference_list_parens = NT_check(table_factor->left_, IRTYPE::kTableReferenceListParens); + + while (table_reference_list_parens != nullptr) { + IR* t_table_reference = NT_check(table_reference_list_parens->left_, IRTYPE::kTableReference); + queue.push_back(t_table_reference); + + table_reference_list_parens = table_reference_list_parens->right_; + } + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown table_factor->left_->type_: %d\n", static_cast(table_factor->left_->type_)); + assert(0); + } + } + } + + assert(!queue.empty()); + for (int i = 0; i < queue.size(); i++) { + IR* curIR = queue[i]; + + switch (curIR->type_) { + case IRTYPE::kSingleTable: { + Table* table = instantiate_single_table(curIR); + res.push_back(table); + + break; + } + case IRTYPE::kDerivedTable: { + Table* table = instantiate_derived_table(curIR); + res.push_back(table); + + break; + } + case IRTYPE::kJoinedTable: { + vector tables = instantiate_joined_table(curIR); + + for (Table* table : tables) { + res.push_back(table); + } + + break; + } + case IRTYPE::kTableReference: { + vector tables = instantiate_table_reference(curIR); + + for (Table* table : tables) { + res.push_back(table); + } + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); + assert(0); + } + } + } + + return res; +} +Table* Instantiator::instantiate_single_table(IR* single_table) { + Table* res = nullptr; + Table* chosenTable = nullptr; + + IR* table_name = NT_check(single_table->left_, IRTYPE::kTableName); + IR* opt_alias = NT_check(single_table->right_, IRTYPE::kOptAlias); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (info->location_ == StmtLocation::slRecursivePart2 && info->recursiveCteName_ != UNREFERENCE && info->recursiveCte_ != nullptr) { + chosenTable = info->recursiveCte_; + + info->recursiveCteName_ = UNREFERENCE; + info->recursiveCte_ = nullptr; + } + else { + int index = globalStatusManger_->get_acce_table_number(); + assert(index > 0); + + int randomNumber = exprInstantiator_->get_random_integer(0, index - 1); + chosenTable = globalStatusManger_->get_acce_table(randomNumber); + } + + res = new Table(chosenTable, info); + instantiate_ident(table_name, res->identifierType_, res->identifierName_); + + if (info->is_duplicated_table(res) && opt_alias->left_ == nullptr) { + opt_alias->left_ = deep_copy(IRTrim_->simple_alias_); + opt_alias->op_->prefix_ = TERMINAL::tAs; + } + + if (opt_alias->left_ != nullptr) { + name_t newName = globalStatusManger_->get_new_table_name(); + IR* alias = NT_check(opt_alias->left_, IRTYPE::kAlias); + + instantiate_ident(alias, IdentifierType::iTable, newName); + + res->identifierName_ = newName; + } + + info->add_used_table(res); + + return res; +} +Table* Instantiator::instantiate_derived_table(IR* derived_table) { + Table* res = nullptr; + + IR* subquery = NT_check(derived_table->left_, IRTYPE::kSubquery); + IR* alias = NT_check(derived_table->right_->left_, IRTYPE::kAlias); + IR* opt_column_list = NT_check(derived_table->right_->right_, IRTYPE::kOptColumnList); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + if (derived_table->op_->prefix_ == TERMINAL::tLateral) { + info->update_acceColumns(); + } + else { + info->acceColumns_ = info->outReferences_; + } + + IR* curNode = subquery->left_; + while (curNode->type_ != IRTYPE::kQueryExpression) { + curNode = curNode->left_; + } + + res = instantiate_query_expression(curNode, StmtLocation::slTableReference, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + res->isSubQuery_ = true; + + name_t newName = globalStatusManger_->get_new_table_name(); + instantiate_ident(alias, IdentifierType::iTable, newName); + res->identifierName_ = newName; + + if (opt_column_list->left_ != nullptr) { + IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); + + for (Column* c: res->columns_) { + name_t name = res->get_acce_column_name(); + res->remove_column_name(name); + + if (name != UNREFERENCE) { + res->add_column_name(c->identifierName_); + c->identifierName_ = name; + } + } + + instantiate_column_list(column_list, res->columns_); + } + + info->acceColumns_.clear(); + info->add_used_table(res); + + return res; +} +vector Instantiator::instantiate_joined_table(IR* joined_table) { + bool isRightJoin = false; + vector res; + + IR* table_reference_left = nullptr; + IR* table_reference_right = nullptr; + IR* table_factor = nullptr; + IR* expr_root = nullptr; + IR* column_list = nullptr; + IR* joined_table_tmp = nullptr; + + IR* unknown = nullptr; + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + table_reference_left = NT_check(joined_table->left_, IRTYPE::kTableReference); + unknown = joined_table->right_; + + if (unknown->left_->type_ == IRTYPE::kNaturalJoinType) { + IR* natural_join_type = NT_check(unknown->left_, IRTYPE::kNaturalJoinType); + + if (natural_join_type->op_->prefix_ == TERMINAL::tNaturalRight) { + isRightJoin = true; + } + } + else if (unknown->left_->type_ == IRTYPE::kOuterJoinType) { + IR* outer_join_type = NT_check(unknown->left_, IRTYPE::kOuterJoinType); + + if (outer_join_type->op_->prefix_ == TERMINAL::tRight) { + isRightJoin = true; + } + } + + if (unknown->right_->type_ == IRTYPE::kTableReference) { + table_reference_right = NT_check(unknown->right_, IRTYPE::kTableReference); + } + else if (unknown->right_->type_ == IRTYPE::kTableFactor) { + table_factor = NT_check(unknown->right_, IRTYPE::kTableFactor); + } + else { + joined_table_tmp = unknown->right_; + + table_reference_right = NT_check(joined_table_tmp->left_, IRTYPE::kTableReference); + + if (joined_table_tmp->right_->type_ == IRTYPE::kExprRoot) { + expr_root = NT_check(joined_table_tmp->right_, IRTYPE::kExprRoot); + } + else { + column_list = NT_check(joined_table_tmp->right_, IRTYPE::kColumnList); + } + } + + if (table_factor != nullptr) { + table_reference_right = new IR(IRTYPE::kTableReference, OP0(), table_factor, nullptr); + } + + vector left; + vector right; + if (isRightJoin) { + right = instantiate_table_reference(table_reference_right); + left = instantiate_table_reference(table_reference_left); + } + else { + left = instantiate_table_reference(table_reference_left); + right = instantiate_table_reference(table_reference_right); + } + + if (table_factor != nullptr && table_reference_right->left_ == table_factor) { + table_reference_right->left_ = nullptr; + deep_delete(table_reference_right); + table_reference_right = nullptr; + } + + vector columnNames = vector(COLUMNNAMEMAX, 0); + for (Table* t : left) { + for (Column* c : t->columns_) { + columnNames[c->identifierName_]++; + } + + res.push_back(t); + } + + for (Table* t : right) { + for (Column* c : t->columns_) { + columnNames[c->identifierName_]++; + } + + res.push_back(t); + } + + if (column_list != nullptr) { + vector duplicatedColumnNames; + for (int i = 0; i < COLUMNNAMEMAX; i++) { + if (columnNames[i] > 1) { + duplicatedColumnNames.push_back(static_cast(i)); + } + } + + if (!duplicatedColumnNames.empty()) { + vector usedColumns; + + random_device rd; + mt19937 r_eng(rd()); + uniform_int_distribution dis(1, duplicatedColumnNames.size()); + + int max = dis(r_eng); + for (int i = 0; i < max; i++) { + usedColumns.push_back(duplicatedColumnNames[i]); + } + + instantiate_column_list(column_list, usedColumns); + } + else { + deep_delete(joined_table_tmp->right_); + joined_table_tmp->right_ = deep_copy(IRTrim_->simple_expr_root_true_); + + joined_table_tmp->op_->middle_ = TERMINAL::tOn; + joined_table_tmp->op_->suffix_ = TERMINAL::tEmpty; + + column_list = nullptr; + } + } + else if (expr_root != nullptr) { + info->update_acceColumns(res, columnNames); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slTableReference); + info->add_out_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + info->acceColumns_.clear(); + } + + return res; +} +void Instantiator::instantiate_where_clause(IR* where_clause) { + IR* expr_root = NT_check(where_clause->left_, IRTYPE::kExprRoot); + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slWhereClause); + info->add_out_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + if (info->location_ == StmtLocation::slRecursivePart2) { + IRTrim_->set_recursive_limit(expr_root); + } + + return; +} +void Instantiator::instantiate_group_clause(IR* group_clause) { + IR* expr_root_list = NT_check(group_clause->left_, IRTYPE::kExprRootList); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + int i = 0; + while (expr_root_list != nullptr && i < info->usedInnerColumns_.size()) { + IR* expr_root = IRTrim_->get_expr_root_columnref(info->usedInnerColumns_[i]); + + deep_delete(expr_root_list->left_); + expr_root_list->left_ = expr_root; + + i++; + + if (i < info->usedInnerColumns_.size() && expr_root_list->right_ == nullptr) { + expr_root_list->right_ = deep_copy(IRTrim_->simple_expr_root_list_); + expr_root_list->op_->middle_ = TERMINAL::tOpComma; + } + + expr_root_list = expr_root_list->right_; + } + + vector usedColumns; + while (expr_root_list != nullptr && !info->acceColumns_.empty()) { + int index = exprInstantiator_->get_random_integer(0, info->acceColumns_.size() - 1); + Column* randomColumn = info->acceColumns_[index]; + + IR* expr_root = IRTrim_->get_expr_root_columnref(randomColumn); + + deep_delete(expr_root_list->left_); + expr_root_list->left_ = expr_root; + + if (find(usedColumns.begin(), usedColumns.end(), randomColumn) == usedColumns.end()) { + usedColumns.push_back(randomColumn); + } + + expr_root_list = expr_root_list->right_; + } + + if (expr_root_list != nullptr) { + deep_delete(expr_root_list->left_); + expr_root_list->left_ = deep_copy(IRTrim_->simple_expr_root_); + + deep_delete(expr_root_list->right_); + + expr_root_list->right_ = nullptr; + expr_root_list->op_->middle_ = TERMINAL::tEmpty; + } + + info->add_out_usedColumns(usedColumns); + + return; +} +void Instantiator::instantiate_having_clause(IR* having_clause) { + IR* expr_root = NT_check(having_clause->left_, IRTYPE::kExprRoot); + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slHavingClause); + info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + return; +} +void Instantiator::instantiate_window_clause(IR* window_clause) { + IR* window_definition_list = NT_check(window_clause->left_, IRTYPE::kWindowDefinitionList); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + while (window_definition_list != nullptr) { + IR* window_definition = NT_check(window_definition_list->left_, IRTYPE::kWindowDefinition); + instantiate_window_definition(window_definition); + + window_definition_list = window_definition_list->right_; + } + + return; +} +void Instantiator::instantiate_window_definition(IR* window_definition) { + IR* window_name = NT_check(window_definition->left_, IRTYPE::kWindowName); + IR* window_spec = NT_check(window_definition->right_, IRTYPE::kWindowSpec); + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + name_t newWindowName = globalStatusManger_->get_new_window_name(); + instantiate_ident(window_name, IdentifierType::iWindow, newWindowName); + + WindowStatus windowStatus = instantiate_window_spec(window_spec); + + info->windowStatusRecord_[newWindowName] = windowStatus; + + return; +} +WindowStatus Instantiator::instantiate_window_spec(IR* window_spec) { + WindowStatus windowStatus = WindowStatus::wsNoInherit; + + IR* window_spec_details = nullptr; + + IR* opt_existing_window_name = nullptr; + IR* opt_partition_clause = nullptr; + IR* opt_window_order_by_clause = nullptr; + IR* opt_window_frame_clause = nullptr; + + IR* unknown = nullptr; + + SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); + + window_spec_details = NT_check(window_spec->left_, IRTYPE::kWindowSpecDetails); + + opt_existing_window_name = NT_check(window_spec_details->left_, IRTYPE::kOptExistingWindowName); + unknown = window_spec_details->right_; + + opt_partition_clause = NT_check(unknown->left_, IRTYPE::kOptPartitionClause); + unknown = unknown->right_; + + opt_window_order_by_clause = NT_check(unknown->left_, IRTYPE::kOptWindowOrderByClause); + opt_window_frame_clause = NT_check(unknown->right_, IRTYPE::kOptWindowFrameClause); + + if (opt_existing_window_name->left_ != nullptr) { + vector inheritedWindows; + + for (auto &it : info->windowStatusRecord_) { + if (it.second != WindowStatus::wsCantBeInherited) { + inheritedWindows.push_back(it.first); + } + } + + if (inheritedWindows.empty()) { + deep_delete(opt_existing_window_name->left_); + opt_existing_window_name->left_ = nullptr; + } + else { + int index = exprInstantiator_->get_random_integer(0, inheritedWindows.size() - 1); + name_t inheritedWindowName = inheritedWindows[index]; + + IR* t_window_name = NT_check(opt_existing_window_name->left_, IRTYPE::kWindowName); + instantiate_ident(t_window_name, IdentifierType::iWindow, inheritedWindowName); + + windowStatus = info->windowStatusRecord_[inheritedWindowName] == WindowStatus::wsWithOrder ? WindowStatus::wsWithOrder : WindowStatus::wsInherit; + } + } + + if (opt_partition_clause->left_ != nullptr) { + if (windowStatus == WindowStatus::wsNoInherit) { + IR* expr_root_list = NT_check(opt_partition_clause->left_, IRTYPE::kExprRootList); + + while (expr_root_list != nullptr) { + IR* expr_root = NT_check(expr_root_list->left_, IRTYPE::kExprRoot); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slWindowClause); + info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + expr_root_list = expr_root_list->right_; + } + } + else { + deep_delete(opt_partition_clause->left_); + + opt_partition_clause->left_ = nullptr; + opt_partition_clause->op_->prefix_ = TERMINAL::tEmpty; + } + } + + if (opt_window_order_by_clause->left_ != nullptr) { + if (windowStatus != WindowStatus::wsWithOrder) { + IR* order_list = NT_check(opt_window_order_by_clause->left_, IRTYPE::kOrderList); + + while (order_list != nullptr) { + IR* expr_root = NT_check(order_list->left_->left_, IRTYPE::kExprRoot); + + exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slWindowClause); + info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); + + order_list = order_list->right_; + } + + windowStatus = WindowStatus::wsWithOrder; + } + else { + deep_delete(opt_window_order_by_clause->left_); + + opt_window_order_by_clause->left_ = nullptr; + opt_window_order_by_clause->op_->prefix_ = TERMINAL::tEmpty; + } + } + + if (opt_window_frame_clause->left_ != nullptr) { + IR* window_frame_units = NT_check(opt_window_frame_clause->left_, IRTYPE::kWindowFrameUnits); + IR* window_frame_extent = NT_check(opt_window_frame_clause->right_, IRTYPE::kWindowFrameExtent); + + if (windowStatus != WindowStatus::wsWithOrder) { + window_frame_units->op_->prefix_ = TERMINAL::tRows; + } + + stack IRStack; + vector iconsts; + IRStack.push(window_frame_extent); + + while (!IRStack.empty()) { + IR* curIR = IRStack.top(); + IRStack.pop(); + + if (curIR == nullptr) { + continue; + } + else if (curIR->type_ == IRTYPE::kIconst) { + iconsts.push_back(curIR); + } + else { + IRStack.push(curIR->right_); + IRStack.push(curIR->left_); + } + } + + for (IR* curIR : iconsts) { + curIR->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); + } + + windowStatus = WindowStatus::wsCantBeInherited; + } + + return windowStatus; +} + +void Instantiator::instantiate_column_list(IR* column_list, vector& columns) { + int i = 0; + + while (column_list != nullptr && i < columns.size()) { + IR* column_name = NT_check(column_list->left_, IRTYPE::kColumnName); + instantiate_ident(column_name, IdentifierType::iColumn, columns[i]); + + i++; + + if (i == columns.size() && column_list->right_ != nullptr) { + deep_delete(column_list->right_); + + column_list->right_ = nullptr; + column_list->op_->middle_ = TERMINAL::tEmpty; + } + else if (i != columns.size() && column_list->right_ == nullptr) { + column_list->right_ = deep_copy(IRTrim_->simple_column_list_); + column_list->op_->middle_ = TERMINAL::tOpComma; + } + + column_list = column_list->right_; + } + + return; +} +void Instantiator::instantiate_column_list(IR* column_list, vector& columns) { + vector columnNames; + + for (Column* c : columns) { + columnNames.push_back(c->identifierName_); + } + + instantiate_column_list(column_list, columnNames); + + return; +} +void Instantiator::instantiate_key_list(IR* key_list, vector& columns) { + int count = 0; + IR* curNode = key_list; + while (curNode != nullptr && count < columns.size()) { + IR* key_part = NT_check(curNode->left_, IRTYPE::kKeyPart); + IR* column_name = NT_check(key_part->left_, IRTYPE::kColumnName); + IR* iconst = nullptr; + + instantiate_ident(column_name, IdentifierType::iColumn, columns[count]->identifierName_); + + if (key_part->right_->type_ != IRTYPE::kOptOrderingDirection) { + if (Column::typeToBasicType_[columns[count]->columnType_] != ColumnBasicType::ctString) { + deep_delete(key_part->right_); + key_part->right_ = new IR(IRTYPE::kOptOrderingDirection, OP0(), nullptr, nullptr); + } + else { + iconst = NT_check(key_part->right_->left_, IRTYPE::kIconst); + } + } + + if (iconst != nullptr) { + int v1 = exprInstantiator_->get_random_integer(1, 32); + iconst->long_val_ = v1; + } + + count++; + + if (count == columns.size() && curNode->right_ != nullptr) { + deep_delete(curNode->right_); + + curNode->right_ = nullptr; + curNode->op_->middle_ = TERMINAL::tEmpty; + } + else if (count != columns.size() && curNode->right_ == nullptr) { + curNode->right_ = deep_copy(IRTrim_->simple_key_part_list_); + curNode->op_->middle_ = TERMINAL::tOpComma; + } + + curNode = curNode->right_; + } + + return; +} +void Instantiator::instantiate_ident(IR* identifier_name, IdentifierType type, name_t name) { + IR* ident = NT_check(identifier_name->left_, IRTYPE::kIdent); + + switch(type) { + case IdentifierType::iColumn: { + ident->str_val_ = "c" + to_string(name); + break; + } + case IdentifierType::iTable: { + ident->str_val_ = "t" + to_string(name); + break; + } + case IdentifierType::iWindow: { + ident->str_val_ = "w" + to_string(name); + break; + } + case IdentifierType::iIndex: { + ident->str_val_ = "i" + to_string(name); + break; + } + case IdentifierType::iConstraint: { + ident->str_val_ = "cc" + to_string(name); + break; + } + case IdentifierType::iView: { + ident->str_val_ = "v" + to_string(name); + break; + } + default: { + fprintf(stderr, "ERROR: Unknown Ident Type: %d\n", static_cast(type)); + assert(0); + } + } + + return; +} + +bool Instantiator::check_foreign_key(Table* table, vector& curTableColumn, vector& otherTableColumn) { + vector types; + + vector acceTable = globalStatusManger_->get_acce_table(IdentifierType::iTable); + acceTable.push_back(table); + + for (Column* c : table->columns_) { + types.push_back(c->columnType_); + } + + Table* chosenTable = acceTable[rand() % acceTable.size()]; + for (Index* index : chosenTable->indexes_) { + bool flag = false; + + for (auto& it : index->columns_) { + if (find(types.begin(), types.end(), it.first->columnType_) == types.end() || it.second == IndexType::itFunctional) { + continue; + } + + for (Column* column : table->columns_) { + if (column->columnType_ != it.first->columnType_ || it.first == column) { + continue; + } + + if (find(curTableColumn.begin(), curTableColumn.end(), column) == curTableColumn.end()) { + curTableColumn.push_back(column); + otherTableColumn.push_back(it.first); + + flag = true; + break; + } + } + } + + if (flag == true) { + break; + } + } + + if (curTableColumn.empty() || curTableColumn.size() != otherTableColumn.size()) { + return false; + } + + return true; +} + +//-----------------------------ExprInstantiator----------------------------- +void ExprInstantiator::instantiate_expr_root(IR* expr_root, vector& acceColumns, StmtLocation location) { + usedColumnsBuffer_.clear(); + + IR* expr = NT_check(expr_root->left_, IRTYPE::kExpr); + instantiate_expr(expr, acceColumns, location); + + return; +} +void ExprInstantiator::instantiate_expr(IR* expr, vector& acceColumns, StmtLocation location) { + stack IRStack; + vector queue; + + IRStack.push(expr); + + while (!IRStack.empty()) { + IR* curIR = IRStack.top(); + IRStack.pop(); + + if (curIR == nullptr) { + continue; + } + + switch (curIR->type_) { + case IRTYPE::kAllSubquery: + case IRTYPE::kInSubquery: { + queue.push_back(curIR); + break; + } + case IRTYPE::kSimpleExpr: { + if (find(ignoreSimpleExpr_.begin(), ignoreSimpleExpr_.end(), curIR->left_->type_) != ignoreSimpleExpr_.end()) { + IRStack.push(curIR->left_); + } + else { + queue.push_back(curIR); + } + + break; + } + default: { + IRStack.push(curIR->left_); + IRStack.push(curIR->right_); + + break; + } + } + } + + for (IR* curIR : queue) { + assert(curIR->type_ == IRTYPE::kInSubquery || curIR->type_ == IRTYPE::kAllSubquery || curIR->type_ == IRTYPE::kSimpleExpr); + + if (curIR->type_ == IRTYPE::kSimpleExpr) { + instantiate_simple_expr(curIR, acceColumns, location); + } + else { + while (curIR->type_ != IRTYPE::kQueryExpression) { + curIR = curIR->left_; + } + + vector tmpUsedColumns = usedColumnsBuffer_; + Table* tmp = instantiator_->instantiate_query_expression(curIR, location, DEFAULTROWNUMBER, 1); + + delete tmp; + usedColumnsBuffer_ = tmpUsedColumns; + } + } + + return; +} +void ExprInstantiator::instantiate_simple_expr(IR* simple_expr, vector& acceColumns, StmtLocation location) { + assert(find(ignoreSimpleExpr_.begin(), ignoreSimpleExpr_.end(), simple_expr->left_->type_) == ignoreSimpleExpr_.end()); + + switch (simple_expr->left_->type_) { + case IRTYPE::kColumnref: { + if (!acceColumns.empty()) { + IR* columnref = NT_check(simple_expr->left_, IRTYPE::kColumnref); + + IR* table_name = nullptr; + IR* column_name = nullptr; + + if (columnref->right_ == nullptr) { + column_name = NT_check(columnref->left_, IRTYPE::kColumnName); + } + else { + table_name = NT_check(columnref->left_, IRTYPE::kTableName); + column_name = NT_check(columnref->right_, IRTYPE::kColumnName); + } + + int index = get_random_integer(0, acceColumns.size() - 1); + Column* column = acceColumns[index]; + + if (column->duplicated_ == ColumnStatus::csDuplication && table_name == nullptr) { + IR* tmp1 = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* tmp2 = new IR(IRTYPE::kTableName, OP0(), tmp1, nullptr); + + table_name = tmp2; + + columnref->left_ = table_name; + columnref->right_ = column_name; + columnref->op_->middle_ = TERMINAL::tOpDot; + } + + if (table_name != nullptr) { + name_t tableName = column->parentTable_->identifierName_; + instantiator_->instantiate_ident(table_name, IdentifierType::iTable, tableName); + } + + name_t columnName = column->identifierName_; + instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, columnName); + + if (find(usedColumnsBuffer_.begin(), usedColumnsBuffer_.end(), column) == usedColumnsBuffer_.end()) { + usedColumnsBuffer_.push_back(column); + } + } + else { + deep_delete(simple_expr->left_); + + simple_expr->left_ = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); + simple_expr->left_->long_val_ = get_random_integer(); + } + + break; + } + case IRTYPE::kIconst: { + IR* iconst = NT_check(simple_expr->left_, IRTYPE::kIconst); + iconst->long_val_ = (rand() % 10) == 0 ? get_random_integer() : get_random_integer(-128, 128); + + break; + } + case IRTYPE::kFconst: { + IR* fconst = NT_check(simple_expr->left_, IRTYPE::kFconst); + fconst->float_val_ = (rand() % 10) == 0 ? get_random_float() : get_random_float(-128, 128); + + break; + } + case IRTYPE::kSconst: { + IR* sconst = NT_check(simple_expr->left_, IRTYPE::kSconst); + sconst->str_val_ = get_random_string(MINSTRINGLENGTH, MAXSTRINGLENGTH); + + break; + } + case IRTYPE::kSubquery: { + IR* subquery = NT_check(simple_expr->left_, IRTYPE::kSubquery); + + IR* curNode = subquery->left_; + while (curNode->type_ != IRTYPE::kQueryExpression) { + curNode = curNode->left_; + } + + Table* tmp = nullptr; + vector tmpUsedColumns = usedColumnsBuffer_; + + if (simple_expr->op_->prefix_ == TERMINAL::tExists) { + tmp = instantiator_->instantiate_query_expression(curNode, StmtLocation::slTargetList, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); + } + else { + tmp = instantiator_->instantiate_query_expression(curNode, StmtLocation::slTargetList, 1, 1); + } + + delete tmp; + usedColumnsBuffer_ = tmpUsedColumns; + + break; + } + case IRTYPE::kTypeCast: { + IR* type_cast = NT_check(simple_expr->left_, IRTYPE::kTypeCast); + instantiate_type_cast(type_cast, acceColumns, location); + + break; + } + case IRTYPE::kFunction: { + IR* function = NT_check(simple_expr->left_, IRTYPE::kFunction); + instantiate_function(function, acceColumns, location); + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown simple_expr->left_->type_: %d\n", static_cast(simple_expr->left_->type_)); + assert(0); + } + } + + return; +} +void ExprInstantiator::instantiate_type_cast(IR* type_cast, vector& acceColumns, StmtLocation location) { + IR* expr = NT_check(type_cast->left_, IRTYPE::kExpr); + IR* cast_type = NT_check(type_cast->right_, IRTYPE::kCastType); + + if (cast_type->left_ != nullptr && cast_type->left_->left_ != nullptr) { + IR* tmp = cast_type->left_; + + if (tmp->left_->type_ == IRTYPE::kFieldLength) { + IR* field_length = NT_check(tmp->left_, IRTYPE::kFieldLength); + IR* iconst = NT_check(field_length->left_, IRTYPE::kIconst); + + iconst->long_val_ = get_random_integer(1, LONG_MAX); + } + else if (tmp->left_->type_ == IRTYPE::kPrecision) { + IR* precision = NT_check(tmp->left_, IRTYPE::kPrecision); + + IR* iconst_left = NT_check(precision->left_, IRTYPE::kIconst); + IR* iconst_right = NT_check(precision->right_, IRTYPE::kIconst); + + iconst_left->long_val_ = get_random_integer(1, 65); + iconst_right->long_val_ = get_random_integer(1, min(static_cast(iconst_left->long_val_), 30)); + } + else { + fprintf(stderr, "ERROR: Unknown cast_type->left_->left_->type_: %d\n", static_cast(cast_type->left_->left_->type_)); + assert(0); + } + } + + instantiate_expr(expr, acceColumns, location); + + return; +} +void ExprInstantiator::instantiate_function(IR* function, vector& acceColumns, StmtLocation location) { + switch (function->left_->type_) { + case IRTYPE::kControlFunction: + case IRTYPE::kMathFunction: + case IRTYPE::kStringFunction: { + stack IRStack; + vector queue; + + IRStack.push(function->left_); + while (!IRStack.empty()) { + IR* curIR = IRStack.top(); + IRStack.pop(); + + if (curIR == nullptr) { + continue; + } + + if (curIR->type_ == IRTYPE::kExpr) { + queue.push_back(curIR); + } + else { + IRStack.push(curIR->left_); + IRStack.push(curIR->right_); + } + } + + for (IR* expr : queue) { + assert(expr->type_ == IRTYPE::kExpr); + + instantiate_expr(expr, acceColumns, location); + } + + break; + } + case IRTYPE::kAggregateFunction: { + if (location != StmtLocation::slTargetList && location != StmtLocation::slHavingClause && location != StmtLocation::slWindowClause) { + deep_delete(function->left_); + function->left_ = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + + break; + } + + IR* aggregate_function = NT_check(function->left_, IRTYPE::kAggregateFunction); + instantiate_aggregate_function(aggregate_function, acceColumns, location); + + break; + } + case IRTYPE::kWindowFunction: { + if (location != StmtLocation::slTargetList) { + deep_delete(function->left_); + function->left_ = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + + break; + } + + IR* window_function = NT_check(function->left_, IRTYPE::kWindowFunction); + instantiate_window_function(window_function, acceColumns, location); + + break; + } + default: { + fprintf(stderr, "ERROR: Unknown function->left_->type_: %d\n", static_cast(function->left_->type_)); + assert(0); + } + } + + return; +} +void ExprInstantiator::instantiate_aggregate_function(IR* aggregate_function, vector& acceColumns, StmtLocation location) { + stack IRStack; + vector queue; + vector captureType = { IRTYPE::kExpr, IRTYPE::kWindowingClause, IRTYPE::kOrderClause, IRTYPE::kSconst }; + + SelectStmtInfo* info = instantiator_->globalStatusManger_->get_cur_selectInfo(); + + IRStack.push(aggregate_function); + while (!IRStack.empty()) { + IR* curIR = IRStack.top(); + IRStack.pop(); + + if (curIR == nullptr) { + continue; + } + + if (find(captureType.begin(), captureType.end(), curIR->type_) != captureType.end()) { + queue.push_back(curIR); + } + else { + IRStack.push(curIR->left_); + IRStack.push(curIR->right_); + } + } + + for (IR* curIR : queue) { + switch (curIR->type_) { + case IRTYPE::kExpr: { + instantiate_expr(curIR, acceColumns, location); + break; + } + case IRTYPE::kWindowingClause: { + IR* window_name_or_spec = NT_check(curIR->left_, IRTYPE::kWindowNameOrSpec); + + if (info->windowStatusRecord_.empty() && window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { + deep_delete(window_name_or_spec->left_); + window_name_or_spec->left_ = deep_copy(instantiator_->IRTrim_->simple_window_spec_); + } + + if (window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { + IR* window_name = NT_check(window_name_or_spec->left_, IRTYPE::kWindowName); + + vector windowNames; + for (auto &it : info->windowStatusRecord_) { + windowNames.push_back(it.first); + } + + assert(!windowNames.empty()); + + int index = get_random_integer(0, windowNames.size() - 1); + name_t windowName = windowNames[index]; + + instantiator_->instantiate_ident(window_name, IdentifierType::iWindow, windowName); + } + else { + IR* window_spec = NT_check(window_name_or_spec->left_, IRTYPE::kWindowSpec); + instantiator_->instantiate_window_spec(window_spec); + } + + break; + } + case IRTYPE::kOrderClause: { + instantiator_->instantiate_order_clause(curIR); + break; + } + case IRTYPE::kSconst: { + curIR->str_val_ = get_random_string(MINSTRINGLENGTH, MAXSTRINGLENGTH); + break; + } + default: { + fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); + assert(0); + } + } + } + + info->hasAggregate = true; + + return; +} +void ExprInstantiator::instantiate_window_function(IR* window_function, vector& acceColumns, StmtLocation location) { + stack IRStack; + vector queue; + vector captureType = { IRTYPE::kExpr, IRTYPE::kWindowingClause, IRTYPE::kIconst }; + + SelectStmtInfo* info = instantiator_->globalStatusManger_->get_cur_selectInfo(); + + IRStack.push(window_function); + + while (!IRStack.empty()) { + IR* curIR = IRStack.top(); + IRStack.pop(); + + if (curIR == nullptr) { + continue; + } + + if (find(captureType.begin(), captureType.end(), curIR->type_) != captureType.end()) { + queue.push_back(curIR); + } + else { + IRStack.push(curIR->left_); + IRStack.push(curIR->right_); + } + } + + for (IR* curIR : queue) { + switch (curIR->type_) { + case IRTYPE::kExpr: { + instantiate_expr(curIR, acceColumns, location); + break; + } + case IRTYPE::kWindowingClause: { + IR* window_name_or_spec = NT_check(curIR->left_, IRTYPE::kWindowNameOrSpec); + + if (info->windowStatusRecord_.empty() && window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { + deep_delete(window_name_or_spec->left_); + window_name_or_spec->left_ = deep_copy(instantiator_->IRTrim_->simple_window_spec_); + } + + if (window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { + IR* window_name = NT_check(window_name_or_spec->left_, IRTYPE::kWindowName); + + vector windowNames; + for (auto &it : info->windowStatusRecord_) { + windowNames.push_back(it.first); + } + + assert(!windowNames.empty()); + + int index = get_random_integer(0, windowNames.size() - 1); + name_t windowName = windowNames[index]; + + instantiator_->instantiate_ident(window_name, IdentifierType::iWindow, windowName); + } + else { + IR* window_spec = NT_check(window_name_or_spec->left_, IRTYPE::kWindowSpec); + instantiator_->instantiate_window_spec(window_spec); + } + + break; + } + case IRTYPE::kIconst: { + curIR->long_val_ = get_random_integer(1, LONG_MAX); + break; + } + default: { + fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); + assert(0); + } + } + } + + return; +} + +long int ExprInstantiator::get_random_integer(long int min, long int max) { + assert(min <= max); + + random_device rd; + mt19937 r_eng(rd()); + uniform_int_distribution dis(min, max); + + return dis(r_eng); +} +double ExprInstantiator::get_random_float(int min, int max) { + random_device rd; + mt19937 r_eng(rd()); + uniform_real_distribution dis(min, max); + + return dis(r_eng); +} +string ExprInstantiator::get_random_string(int minLength, int maxLength) { + random_device rd; + mt19937 r_eng(rd()); + uniform_int_distribution charNumber(32, 126); + uniform_int_distribution stringLength(minLength, maxLength); + + int length = stringLength(r_eng); + string res = "\'"; + + for (int i = 0; i < length; i++) { + char tmp = charNumber(r_eng); + + if (tmp == '\'' || tmp == '\\') { + res += "\\"; + } + + res += tmp; + } + + res += "\'"; + + return res; +} diff --git a/src/mutate.cpp b/src/mutate.cpp new file mode 100755 index 0000000..d0108f5 --- /dev/null +++ b/src/mutate.cpp @@ -0,0 +1,1359 @@ +#include "../include/mutate.h" +#include "../include/ast.h" +#include "../include/define.h" + +#include "../parser/bison_parser.h" +#include "../parser/flex_lexer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; +namespace fs = std::filesystem; + +double get_random_double(int min, int max) { + random_device rd; + mt19937 r_eng(rd()); + uniform_real_distribution dis(min, max); + + return dis(r_eng); +} + +//-----------------------------Mutator----------------------------- + +vector Mutator::stmtIRType_ = { + IRTYPE::kCreateTableStmt, + IRTYPE::kCreateViewStmt, + IRTYPE::kCreateIndexStmt, + IRTYPE::kSelectStmt, + IRTYPE::kDropIndexStmt, + IRTYPE::kDropTableStmt, + IRTYPE::kDropViewStmt, + IRTYPE::kDeleteStmt, + IRTYPE::kUpdateStmt, + IRTYPE::kInsertStmt, + IRTYPE::kAlterTableStmt +}; +vector Mutator::clauseIRType_ = { + IRTYPE::kAlterListItem, + IRTYPE::kValues, + IRTYPE::kUpdateElem, + IRTYPE::kDefaultAttribute, + IRTYPE::kCheckConstraint, + IRTYPE::kKeyPartWithExpression, + IRTYPE::kOptWindowClause, + IRTYPE::kOptHavingClause, + IRTYPE::kWhereClause, + IRTYPE::kFromClause, + IRTYPE::kSelectItem +}; + +Mutator::Mutator() { + random_device rd; + srand(rd()); + + startTime = chrono::steady_clock::now(); + + not_mutatable_types_.insert({ IRTYPE::kParseToplevel, IRTYPE::kStmtmulti, IRTYPE::kStmt }); + + return; +} +Mutator::~Mutator() { + free_IR_library(); + free_IR_config_info(); + + return; +} + +bool Mutator::init_IR_library(string dirPath) { + vector IRFileNames = get_all_files_in_dir(dirPath.c_str()); + if (IRFileNames.empty()) { + fprintf(stderr, "ERROR: No IR library File in dirPath!!!\n"); + return false; + } + + for (string fileName : IRFileNames) { + ifstream inputFile(fileName); + string sql; + + while (getline(inputFile, sql)) { + if (sql.empty()) + continue; + + IR* p = IR_parser(sql.c_str()); + if (p == nullptr) + continue; + + add_ir_to_library(p); + deep_delete(p); + } + } + + return true; +} + +void Mutator::free_IR_library() { + for (IR* p : IR_library_[IRTYPE::kParseToplevel]) { + if (p) + deep_delete(p); + } + + return; +} + +bool Mutator::init_IR_config_info(string filePath) { + char flag = 0; + IRTYPE type = IRTYPE::kNone; + int count = 0; + + FILE* fd = fopen(filePath.c_str(), "r"); + if (!fd){ + fprintf(stderr, "IR_config file is not exists!!\n"); + return false; + } + + while (!feof(fd)) { + if (!flag) { + int tmpType = 0; + fscanf(fd, "%d %d\n", &tmpType, &count); + + type = static_cast(tmpType); + + if (IRInfo_.find(static_cast(type)) != IRInfo_.end()) { + fprintf(stderr, "ERROR: IR_config file has duplication type: %d!!\n", type); + return false; + } + + IRInfo_[type] = new IRInfoManger(); + IRInfo_[type]->curIRType_ = type; + + OpInfo_[type] = new OperatorManger(); + OpInfo_[type]->curIRType_ = type; + + IRTypeCount_[type] = { 0, 0 }; + + flag = 1; + } + else { + int prefix = 0; + int left = 0; + int middle = 0; + int right = 0; + int suffix = 0; + + for (int i = 0; i < count; i++) { + fscanf(fd, "%d %d %d %d %d\n", &prefix, &left, &middle, &right, &suffix); + + IRInfomation* tmp = new IRInfomation(prefix, left, middle, right, suffix); + IRInfo_[type]->add_IRInfomation(tmp); + } + + flag = 0; + type = IRTYPE::kNone; + count = 0; + } + } + + fclose(fd); + + return true; +} + +void Mutator::free_IR_config_info() { + for (auto& it : IRInfo_) { + delete it.second; + } + + for (auto& it : OpInfo_) { + delete it.second; + } + + return; +} + +uint64_t Mutator::hash(string& sql) { + const void* key = static_cast(sql.c_str()); + int len = sql.size(); + + const uint64_t m = 0xc6a4a7935bd1e995; + const int r = 47; + uint64_t h = 0xdeadbeefdeadbeef ^ (len * m); + + const uint64_t* data = static_cast(key); + const uint64_t* end = data + (len / 8); + + while (data != end) + { + uint64_t k = *data++; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + } + + const unsigned char* data2 = (const unsigned char*)data; + + switch (len & 7) + { + case 7: h ^= uint64_t(data2[6]) << 48; + case 6: h ^= uint64_t(data2[5]) << 40; + case 5: h ^= uint64_t(data2[4]) << 32; + case 4: h ^= uint64_t(data2[3]) << 24; + case 3: h ^= uint64_t(data2[2]) << 16; + case 2: h ^= uint64_t(data2[1]) << 8; + case 1: h ^= uint64_t(data2[0]); + h *= m; + }; + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return h; +} + +vector Mutator::get_all_files_in_dir(const char* dirPath) { + vector res; + + fs::path dir = dirPath; + if (!fs::exists(dir)) { + return res; + } + + for (const fs::directory_entry& entry : fs::directory_iterator(dir)) { + if (entry.is_regular_file()) { + res.push_back(entry.path().string()); + } + } + + return res; +} + +ParseToplevel* Mutator::parser(const char* sql) { + + yyscan_t scanner; + YY_BUFFER_STATE state; + ParseToplevel* p = new ParseToplevel(); + + if (ff_lex_init(&scanner)) { + return NULL; + } + + state = ff__scan_string(sql, scanner); + + int ret = ff_parse(p, scanner); + + ff__delete_buffer(state, scanner); + ff_lex_destroy(scanner); + + if (ret != 0) { + p->deep_delete(); + return NULL; + } + + return p; +} + +IR* Mutator::IR_parser(const char* sql) { + ParseToplevel* p = parser(sql); + if (p == nullptr) + return nullptr; + + IR* res = p->translate(); + p->deep_delete(); + + return res; +} + +bool Mutator::add_ir_to_library(IR* root) { + extract_struct(root); + IR* newRoot = deep_copy(root); + + if (!add_ir_to_library_no_deepcopy(newRoot)) { + deep_delete(newRoot); + return false; + } + + return true; +} + +bool Mutator::add_ir_to_library_no_deepcopy(IR* root) { + bool flag = false; + + if (root->left_) flag |= add_ir_to_library_no_deepcopy(root->left_); + + if (root->right_) flag |= add_ir_to_library_no_deepcopy(root->right_); + + IRTYPE type = root->type_; + + string tmpStr = root->to_string(); + uint64_t h = hash(tmpStr); + if (find(IR_library_hash_[type].begin(), IR_library_hash_[type].end(), h) != IR_library_hash_[type].end()) { + if ((type == IRTYPE::kParseToplevel) && flag) { + IR_library_[type].push_back(root); + } + + return false | flag; + } + + IR_library_[type].push_back(root); + IR_library_hash_[type].insert(h); + + return true; +} + +void Mutator::extract_struct(IR* root) { + IRTYPE type = root->type_; + + if (root->left_) extract_struct(root->left_); + if (root->right_) extract_struct(root->right_); + + if (root->left_ || root->right_) return; + + switch (root->type_) { + case IRTYPE::kIconst: + root->long_val_ = 1; + break; + case IRTYPE::kFconst: + root->float_val_ = 1.0; + break; + case IRTYPE::kSconst: + root->str_val_ = "'x'"; + break; + case IRTYPE::kIdent: + root->str_val_ = "x"; + break; + } + + return; +} + +void Mutator::update_status(InputInfo* input, unsigned int execStatus, bool isValid) { + unsigned int reward = get_cur_reward(); + bool hasNewCoverage = (execStatus == 1 || execStatus == 2); + + IRInfoManger* manger = IRInfo_[input->MutateIRType_]; + manger->update_count(&input->MutateContext_, input->MutateIRInfoItem_, hasNewCoverage, reward); + +#ifdef ORIGINAL + OperatorManger* OpManger = OpInfo_[input->MutateIRType_]; + OpManger->update_count(&input->MutateContext_, input->MutateOperatorItem_, hasNewCoverage, reward); +#endif + + if (hasNewCoverage == true){ + if (execStatus == 1) { + IRTypeCount_[input->MutateIRType_].first += reward; + } + else{ + IRTypeCount_[input->MutateIRType_].first += reward * REWARDNEWCOVERAGE; + } + + if (isValid == true) { + add_ir_to_library(input->input_); + } + } + else { + IRTypeCount_[input->MutateIRType_].second += reward; + } + + return; +} + +vector Mutator::mutate_all(const char* sql) { + vector res; + deque> q; + + vector IRTypeRank; + vector probabilityRank; + + map>> indexes; + + IR* originRoot = IR_parser(sql); + if (originRoot == nullptr) + return res; + + IRContextS tmp = { 0 }; + q.push_back({originRoot, tmp}); + + while (!q.empty()) { + IR* curIR = q.front().first; + IRContextS curContext = q.front().second; + q.pop_front(); + + if (curIR == nullptr) { + continue; + } + + IRContextS nextContext = { 0 }; + + if (find(stmtIRType_.begin(), stmtIRType_.end(), curIR->type_) != stmtIRType_.end()) { + nextContext.stmt_ = static_cast(curIR->type_); + } + else { + nextContext.stmt_ = curContext.stmt_; + } + + if (find(clauseIRType_.begin(), clauseIRType_.end(), curIR->type_) != clauseIRType_.end()) { + nextContext.clause_ = static_cast(curIR->type_); + } + else { + nextContext.clause_ = curContext.clause_; + } + + if (curIR->type_ == IRTYPE::kSubquery) { + nextContext.inSubquery_ = 1; + } + else { + nextContext.inSubquery_ = curContext.inSubquery_; + } + + nextContext.parentIRType_ = curIR->type_; + nextContext.parentIRItem_ = IRInfo_[curIR->type_]->get_index_of_IRInfo(curIR); + + q.push_back({curIR->left_, nextContext }); + q.push_back({ curIR->right_ , nextContext }); + + if (not_mutatable_types_.find(curIR->type_) != not_mutatable_types_.end()) { + continue; + } + + unsigned int chosenNumber = IRTypeCount_[curIR->type_].first + IRTypeCount_[curIR->type_].second; + if (find(IRTypeRank.begin(), IRTypeRank.end(), curIR->type_) == IRTypeRank.end() && chosenNumber > IRTYPEUPDATETHRESHOLD) { + if (IRTypeRank.size() < TOPNUMBER) { + IRTypeRank.push_back(curIR->type_); + } + else { + IRTYPE tLeft = IRTypeRank[IRTypeRank.size() - 1]; + + double pLeft = static_cast(IRTypeCount_[tLeft].first) / (IRTypeCount_[tLeft].first + IRTypeCount_[tLeft].second); + double pRight = static_cast(IRTypeCount_[curIR->type_].first) / chosenNumber; + + if (pLeft < pRight) { + IRTypeRank[IRTypeRank.size() - 1] = curIR->type_; + } + } + } + + for (int i = IRTypeRank.size() - 1; i > 0; i--) { + IRTYPE tLeft = IRTypeRank[i - 1]; + IRTYPE tRight = IRTypeRank[i]; + + double pLeft = static_cast(IRTypeCount_[tLeft].first) / (IRTypeCount_[tLeft].first + IRTypeCount_[tLeft].second); + double pRight = static_cast(IRTypeCount_[tRight].first) / (IRTypeCount_[tRight].first + IRTypeCount_[tRight].second); + + if (pLeft > pRight) { + break; + } + + IRTYPE tmp = IRTypeRank[i]; + IRTypeRank[i] = IRTypeRank[i - 1]; + IRTypeRank[i - 1] = tmp; + } + + indexes[curIR->type_].push_back({ curIR, curContext }); + } + + double expectSum = 0; + for (IRTYPE t : IRTypeRank) { + expectSum += static_cast(IRTypeCount_[t].first) / (IRTypeCount_[t].first + IRTypeCount_[t].second); + } + + for (int i = 0; i < IRTypeRank.size(); i++) { + IRTYPE t = IRTypeRank[i]; + double p = static_cast(IRTypeCount_[t].first) / (IRTypeCount_[t].first + IRTypeCount_[t].second); + + probabilityRank.push_back(p / expectSum); + } + + double heat = get_cur_heat(); + for (auto& it : indexes) { + IRTYPE curType = it.first; + unsigned int chosenNumber = IRTypeCount_[curType].first + IRTypeCount_[curType].second; + + for (pair& node : it.second) { + IR* curNode = nullptr; + IRContextS curContext = { 0 }; + + double randomNumber = get_random_double(0, 1); + + if (chosenNumber < IRTYPEUPDATETHRESHOLD || randomNumber < heat) { + curNode = node.first; + curContext = node.second; + } + else { + double tmpRand = get_random_double(0, 1); + IRTYPE tmpType = IRTYPE::kNone; + + for (int i = 0; i < probabilityRank.size(); i++) { + if (tmpRand >= probabilityRank[i]) { + tmpRand -= probabilityRank[i]; + continue; + } + + tmpType = IRTypeRank[i]; + break; + } + + if (tmpType == IRTYPE::kNone) { + curNode = node.first; + curContext = node.second; + } + else { + pair& tmp = indexes[tmpType][rand() % indexes[tmpType].size()]; + curNode = tmp.first; + curContext = tmp.second; + } + } + +#ifdef ORIGINAL + vector newInputInfos = original_mutate(curNode, curContext, heat); +#else + vector newInputInfos = mutate(curNode, curContext, heat); +#endif + + for (InputInfo* newInputInfo : newInputInfos) { + newInputInfo->input_ = get_new_tree(originRoot, curNode, newInputInfo->input_); + + extract_struct(newInputInfo->input_); + + string tmpStr = newInputInfo->input_->to_string(); + + uint64_t h = hash(tmpStr); + if (sql_hash_.find(h) != sql_hash_.end()) { + delete newInputInfo; + continue; + } + sql_hash_.insert(h); + + IR* checkSql = check_sql(tmpStr); + if (checkSql == nullptr) { + delete newInputInfo; + continue; + } + else { + deep_delete(newInputInfo->input_); + newInputInfo->input_ = checkSql; + } + + res.push_back(newInputInfo); + } + } + } + + deep_delete(originRoot); + + mutateNumber_.push_back(res.size()); + seedCount_++; + + return res; +} + +vector Mutator::mutate(IR* root, IRContextS context, double heat) { + vector res; + + IRInfoManger* manger = IRInfo_[root->type_]; + vector indexes = manger->get_IRInfo_index(&context, heat); + + for (unsigned short int index : indexes) { + char flag = (rand() % 3) + 1; + + IR* left = nullptr; + IR* right = nullptr; + + IRInfomation* tmpIRInformation = manger->get_IRInfomation(index); + + InputInfo* newInputInfo = new InputInfo(); + newInputInfo->MutateIRType_ = root->type_; + newInputInfo->MutateIRInfoItem_ = index; + newInputInfo->MutateContext_ = context; + + if ((flag & 1) || ((root->left_ ? root->left_->type_ : IRTYPE::kNone) != tmpIRInformation->left_)) { + IR* tmp = get_ir_from_library(tmpIRInformation->left_); + left = deep_copy(tmp); + } + else { + left = deep_copy(root->left_); + } + + if ((flag & 2) || ((root->right_ ? root->right_->type_ : IRTYPE::kNone) != tmpIRInformation->right_)) { + IR* tmp = get_ir_from_library(tmpIRInformation->right_); + right = deep_copy(tmp); + } + else { + right = deep_copy(root->right_); + } + + IR* newIRTree = new IR(root, left, right); + + newIRTree->op_->prefix_ = tmpIRInformation->prefix_; + newIRTree->op_->middle_ = tmpIRInformation->middle_; + newIRTree->op_->suffix_ = tmpIRInformation->suffix_; + + newInputInfo->input_ = newIRTree; + + res.push_back(newInputInfo); + } + + return res; +} + +IR* Mutator::get_ir_from_library(IRTYPE type) { + if (type == IRTYPE::kNone) + return nullptr; + + if (IR_library_[type].empty()) { + fprintf(stderr, "ERROR: Lack IRTYPE : %d!!!\n", static_cast(type)); + assert(0); + } + + return IR_library_[type][rand() % (IR_library_[type].size())]; +} + +IR* Mutator::get_new_tree(IR* oldIRRoot, IR* curIR, IR* newIR) { + assert(oldIRRoot && curIR && newIR); + + IR* res = nullptr; + IR* left = nullptr; + IR* right = nullptr; + + if (oldIRRoot->left_ != nullptr) { + if (oldIRRoot->left_ == curIR) + left = newIR; + else + left = get_new_tree(oldIRRoot->left_, curIR, newIR); + } + + if (oldIRRoot->right_ != nullptr) { + if (oldIRRoot->right_ == curIR) + right = newIR; + else + right = get_new_tree(oldIRRoot->right_, curIR, newIR); + } + + res = new IR(oldIRRoot, left, right); + + return res; +} + +void Mutator::print_information(string outputPath) { + print_IRType_information(outputPath); + print_IRInfo_information(outputPath); + print_Mutate_number(outputPath); + +#ifdef ORIGINAL + print_OpInfo_information(outputPath); +#endif + + return; +} +void Mutator::print_IRType_information(string outputPath) { + ofstream outFileIRType(outputPath + "IRType_Information", ios::trunc); + + if (outFileIRType) { + for (auto& it : IRTypeCount_) { + IRTYPE curType = it.first; + pair& count = it.second; + + outFileIRType << "Current IRTYPE: " << to_string(curType) << endl; + outFileIRType << "\tSuccesses: " << to_string(count.first) << ", Failed: " << to_string(count.second) << ", Total: " << to_string(count.first + count.second) << endl << endl; + } + + outFileIRType.close(); + } + else { + cout << "ERROR: Can't Write IRType_Information File!!!" << endl; + } + + return; +} +void Mutator::print_IRInfo_information(string outputPath) { + ofstream outFileIRInfo(outputPath + "IRInfo_information", ios::trunc); + + if (outFileIRInfo) { + for (auto& it : IRInfo_) { + string info = it.second->print_IRInformation_status(); + outFileIRInfo << info << endl; + } + } + else { + cout << "ERROR: Can't Write IRInfo_information File!!!" << endl; + } + + return; +} +void Mutator::print_Mutate_number(string outputPath) { + ofstream outFileMutate(outputPath + "Mutate_number", ios::trunc); + + if (outFileMutate) { + for (unsigned short n : mutateNumber_) { + outFileMutate << n << endl; + } + } + else { + cout << "ERROR: Can't Write Mutate_number File!!!" << endl; + } + + return; +} +void Mutator::print_OpInfo_information(string outputPath) { + ofstream outFileIRInfo(outputPath + "OpInfo_information", ios::trunc); + + if (outFileIRInfo) { + pair OpReplace = { 0, 0 }; + pair OpInsert = { 0, 0 }; + pair OpDelete = { 0, 0 }; + + for (auto& it : OpInfo_) { + vector& chosenCounts = it.second->OpInfoChosenCount_; + vector& failedCounts = it.second->OpInfoFailedCount_; + + OpReplace.first += chosenCounts[0]; + OpReplace.second += failedCounts[0]; + + OpInsert.first += chosenCounts[1]; + OpInsert.second += failedCounts[1]; + + OpDelete.first += chosenCounts[2]; + OpDelete.second += failedCounts[2]; + + string info = it.second->print_OperatorInformation_status(); + outFileIRInfo << info << endl; + } + + outFileIRInfo << "Replace Operator\n\tTotal Chosen Number: " << to_string(OpReplace.first) << ", Total Failed Number: " << to_string(OpReplace.second) << ", Accuracy Rate: " << to_string(1 - static_cast(OpReplace.second) / OpReplace.first) << "%" << endl; + outFileIRInfo << "Insert Operator\n\tTotal Chosen Number: " << to_string(OpInsert.first) << ", Total Failed Number: " << to_string(OpInsert.second) << ", Accuracy Rate: " << to_string(1 - static_cast(OpInsert.second) / OpInsert.first) << "%" << endl; + outFileIRInfo << "Delete Operator\n\tTotal Chosen Number: " << to_string(OpDelete.first) << ", Total Failed Number: " << to_string(OpDelete.second) << ", Accuracy Rate: " << to_string(1 - static_cast(OpDelete.second) / OpDelete.first) << "%" << endl; + } + else { + cout << "ERROR: Can't Write OpInfo_information File!!!" << endl; + } + + return; +} + +unsigned int Mutator::get_duration_ms() { + chrono::time_point curTime = chrono::steady_clock::now(); + + return chrono::duration_cast(curTime - startTime).count(); +} +double Mutator::get_cur_heat() { + unsigned int duration = get_duration_ms(); + + return static_cast(1) / (static_cast(duration / TIMETHRESHOLD) + 1); +} +unsigned int Mutator::get_cur_reward() { + unsigned int duration = get_duration_ms(); + + return 1 + (duration / TIMETHRESHOLD) * REWARDINCREMENT; +} + +vector Mutator::original_mutate(IR* root, IRContextS context, double heat) { + vector res; + + OperatorManger* OpManger = OpInfo_[root->type_]; + vector indexes = OpManger->get_OpInfo_index(&context, heat); + + for (unsigned short int index : indexes) { + MutateOperator op = OpManger->get_operator(index); + IR* tmp = nullptr; + + switch (op) { + case MutateOperator::moReplace: { + tmp = strategy_replace(root); + break; + } + case MutateOperator::moInsert: { + tmp = strategy_insert(root); + break; + } + case MutateOperator::moDelete: { + tmp = strategy_delete(root); + break; + } + } + + if (tmp != nullptr) { + IRInfoManger* manger = IRInfo_[tmp->type_]; + manger->get_IRInfo_index(&context, get_cur_heat()); + + InputInfo* newInputInfo = new InputInfo(); + + newInputInfo->MutateIRType_ = root->type_; + newInputInfo->MutateIRInfoItem_ = manger->get_index_of_IRInfo(tmp); + newInputInfo->MutateContext_ = context; + newInputInfo->MutateOperatorItem_ = index; + + if (newInputInfo->MutateIRInfoItem_ != ERRORINDEX) { + manger->IRInfoChosenCount_[newInputInfo->MutateIRInfoItem_]++; + } + + newInputInfo->input_ = tmp; + + res.push_back(newInputInfo); + } + else { + OpManger->OpInfoFailedCount_[index]++; + OpManger->update_count(&context, index, false, get_cur_reward()); + } + } + + return res; +} + +IR* Mutator::strategy_delete(IR* root) { + IR* res = nullptr; + int flag = 0; + + if (root->left_ != nullptr && root->right_ != nullptr) { + flag = (rand() % 3) + 1; + } + else if (root->left_ != nullptr) { + flag = 1; + } + else if (root->right_ != nullptr) { + flag = 2; + } + else { + return nullptr; + } + + res = deep_copy(root); + + if ((flag & 1) == 1) { + deep_delete(res->left_); + res->left_ = nullptr; + } + + if ((flag & 2) == 2) { + deep_delete(res->right_); + res->right_ = nullptr; + } + + return res; +} +IR* Mutator::strategy_insert(IR* root) { + IRTYPE curType = root->type_; + + if (root->right_ == nullptr && root->left_ != nullptr) { + IRTYPE leftNodeType = root->left_->type_; + + for (int i = 0; i < 4; i++) { + IR* tmp = get_ir_from_library(curType); + + if (tmp != nullptr && tmp->left_ != nullptr && tmp->left_->type_ == leftNodeType && tmp->right_ != nullptr) { + IR* res = deep_copy(root); + res->right_ = deep_copy(tmp->right_); + + res->op_->prefix_ = tmp->op_->prefix_; + res->op_->middle_ = tmp->op_->middle_; + res->op_->suffix_ = tmp->op_->suffix_; + + return res; + } + } + } + else if (root->right_ != nullptr && root->left_ == nullptr) { + IRTYPE rightNodeType = root->right_->type_; + + for (int i = 0; i < 4; i++) { + IR* tmp = get_ir_from_library(curType); + + if (tmp != nullptr && tmp->right_ != nullptr && tmp->right_->type_ == rightNodeType && tmp->left_ != nullptr) { + IR* res = deep_copy(root); + res->left_ = deep_copy(tmp->left_); + + res->op_->prefix_ = tmp->op_->prefix_; + res->op_->middle_ = tmp->op_->middle_; + res->op_->suffix_ = tmp->op_->suffix_; + + return res; + } + } + } + else if (root->right_ == nullptr && root->left_ == nullptr) { + for (int i = 0; i < 4; i++) { + IR* tmp = get_ir_from_library(curType); + + if (tmp != nullptr && (tmp->left_ != nullptr || tmp->right_ != nullptr)) { + IR* res = deep_copy(root); + res->left_ = deep_copy(tmp->left_); + res->right_ = deep_copy(tmp->right_); + + res->op_->prefix_ = tmp->op_->prefix_; + res->op_->middle_ = tmp->op_->middle_; + res->op_->suffix_ = tmp->op_->suffix_; + + return res; + } + } + } + + return nullptr; +} +IR* Mutator::strategy_replace(IR* root) { + IR* res = nullptr; + int flag = 0; + + if (root->left_ != nullptr && root->right_ != nullptr) { + flag = (rand() % 3) + 1; + } + else if (root->left_ != nullptr) { + flag = 1; + } + else if (root->right_ != nullptr) { + flag = 2; + } + else { + return nullptr; + } + + res = deep_copy(root); + + if ((flag & 1) == 1) { + IR* tmpLeft = get_ir_from_library(res->left_->type_); + + if (tmpLeft != nullptr) { + deep_delete(res->left_); + res->left_ = deep_copy(tmpLeft); + } + } + + if ((flag & 2) == 2) { + IR* tmpRight = get_ir_from_library(res->right_->type_); + + if (tmpRight != nullptr) { + deep_delete(res->right_); + res->right_ = deep_copy(tmpRight); + } + } + + return res; +} + +IR* Mutator::check_sql(string& sql) { + IR* res = IR_parser(sql.c_str()); + + totalMutate_++; + if (res == nullptr) { + failedMutate_++; + } + + return res; +} + +//-----------------------------IRInfomation----------------------------- +IRInfomation::IRInfomation(int prefix, int left, int middle, int right, int suffix) { + prefix_ = static_cast(prefix); + left_ = static_cast(left); + middle_ = static_cast(middle); + right_ = static_cast(right); + suffix_ = static_cast(suffix); + + return; +} +IRInfomation::IRInfomation(IR* root) { + prefix_ = root->op_->prefix_; + left_ = root->left_ != nullptr ? root->left_->type_ : IRTYPE::kNone; + middle_ = root->op_->middle_; + right_ = root->right_ != nullptr ? root->right_->type_ : IRTYPE::kNone; + suffix_ = root->op_->suffix_; + + return; +} + +bool IRInfomation::operator!=(IRInfomation* info) { + if (info->prefix_ != prefix_) { + return true; + } + + if (info->left_ != left_) { + return true; + } + + if (info->middle_ != middle_) { + return true; + } + + if (info->right_ != right_) { + return true; + } + + if (info->suffix_ != suffix_) { + return true; + } + + return false; +} + +//-----------------------------IRInfoManger----------------------------- +IRInfoManger::IRInfoManger() {} +IRInfoManger::~IRInfoManger() { + for (IRInfomation* info : IRInfomation_) { + delete info; + } + + return; +} + +void IRInfoManger::create_new_context(IRContextS* context) { + uint64_t index = *reinterpret_cast(context); + + assert(contextDependentCount_.find(index) == contextDependentCount_.end()); + + for (int i = 0; i < IRInfomation_.size(); i++) { + contextDependentCount_[index].push_back({0, 0}); + } + + return; +} + +void IRInfoManger::update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward) { + uint64_t index = *reinterpret_cast(context); + + assert(contextDependentCount_.find(index) != contextDependentCount_.end()); + + if (item == ERRORINDEX) { + return; + } + + if (hasNewCoverage == true) { + contextDependentCount_[index][item].first += reward; + } + else { + contextDependentCount_[index][item].second += reward; + } + + return; +} + +void IRInfoManger::add_IRInfomation(IRInfomation* info) { + IRInfomation_.push_back(info); + IRInfoChosenCount_.push_back(0); + return; +} +IRInfomation* IRInfoManger::get_IRInfomation(unsigned short int index) { + assert(index < IRInfomation_.size() && index >= 0); + IRInfoChosenCount_[index]++; + return IRInfomation_[index]; +} + +#ifdef BALANCE +vector IRInfoManger::get_IRInfo_index(IRContextS* context, double heat) { + vector res; + uint64_t index = *reinterpret_cast(context); + + if (contextDependentCount_.find(index) == contextDependentCount_.end()) { + create_new_context(context); + } + + for (int i = 0; i < MUTATENUMBER; i++) { + double randomNumber = get_random_double(0, 1); + if (randomNumber < heat) { + res.push_back(rand() % IRInfomation_.size()); + } + else { + int maxIndex = ERRORINDEX; + double maxExpect = 0.0; + vector>& counts = contextDependentCount_[index]; + + for (int i = 0; i < counts.size(); i++) { + unsigned int totalNumber = counts[i].first + counts[i].second; + if (totalNumber <= IRINFOUPDATETHRESHOLD) { + continue; + } + + double expect = counts[i].first / totalNumber; + if (expect > maxExpect) { + maxIndex = i; + maxExpect = expect; + } + } + + if (maxIndex != ERRORINDEX) { + res.push_back(maxIndex); + } + else { + res.push_back(rand() % IRInfomation_.size()); + } + } + } + + return res; +} +#else +vector IRInfoManger::get_IRInfo_index(IRContextS* context, double heat) { + vector res; + vector skip; + uint64_t index = *reinterpret_cast(context); + + if (contextDependentCount_.find(index) == contextDependentCount_.end()) { + create_new_context(context); + } + + unsigned short int maxExpectIndex = ERRORINDEX; + double maxExpect = 0; + + vector>& curContextCount = contextDependentCount_[index]; + int mutateNumber = curContextCount.size(); + + for (int i = 0; i < curContextCount.size(); i++) { + pair& count = curContextCount[i]; + + unsigned int chosenNumber = count.first + count.second; + if (chosenNumber > IRINFOUPDATETHRESHOLD) { + double expect = static_cast(count.first) / chosenNumber; + + if (expect > maxExpect) { + maxExpectIndex = i; + maxExpect = expect; + } + } + + double tmp = get_random_double(0, 1); + if (chosenNumber <= IRINFOUPDATETHRESHOLD || tmp < heat) { + res.push_back(i); + mutateNumber--; + } + else { + skip.push_back(i); + } + } + + if (maxExpectIndex == ERRORINDEX) { + for (unsigned short int i : skip) { + res.push_back(i); + } + } + else { + while (mutateNumber > 0) { + res.push_back(maxExpectIndex); + mutateNumber--; + } + } + + return res; +} +#endif + +unsigned short int IRInfoManger::get_index_of_IRInfo(IR* root) { + int res = ERRORINDEX; + IRInfomation curIRInfo(root); + + for (int i = 0; i < IRInfomation_.size(); i++) { + if (*IRInfomation_[i] != &curIRInfo) { + continue; + } + + res = i; + break; + } + + return res; +} + +string IRInfoManger::print_IRInformation_status() { + unsigned long totalSuccessCount = 0; + unsigned long totalFailedCount = 0; + + string res = "Current IRTYPE: " + to_string(curIRType_) + "\n"; + + for (int i = 0; i < IRInfomation_.size(); i++) { + unsigned long successCount = 0; + unsigned long failedCount = 0; + IRInfomation* tmp = IRInfomation_[i]; + + res += "--IRInfo " + to_string(i) + ": " + to_string(tmp->prefix_) + " " + to_string(tmp->left_) + " " + to_string(tmp->middle_) + " " + to_string(tmp->right_) + " " + to_string(tmp->suffix_) + ":\n"; + res += "--Total Chosen Number: " + to_string(IRInfoChosenCount_[i]) + "\n"; + + for (auto& it : contextDependentCount_) { + uint64_t context = it.first; + pair& count = it.second[i]; + + successCount += count.first; + totalSuccessCount += count.first; + failedCount += count.second; + totalFailedCount += count.second; + + res += "\tCurrent Context: " + to_string(context) + ", Successes: " + to_string(count.first) + ", Failed: " + to_string(count.second) + ", Total: " + to_string(count.first + count.second) + "\n"; + } + + res += "--Successes: " + to_string(successCount) + ", Failed: " + to_string(failedCount) + ", Total: " + to_string(successCount + failedCount) + "\n"; + } + + res += "Total Successes: " + to_string(totalSuccessCount) + ", Total Failed: " + to_string(totalFailedCount) + ", Total: " + to_string(totalSuccessCount + totalFailedCount) + "\n\n"; + + return res; +} + +//-----------------------------InputInfo----------------------------- +InputInfo::InputInfo() {} +InputInfo::~InputInfo() { + deep_delete(input_); + return; +} + +//-----------------------------OperatorManger----------------------------- +OperatorManger::OperatorManger() { + OperatorInfomation_ = { MutateOperator::moReplace, MutateOperator::moInsert, MutateOperator::moDelete }; + OpInfoChosenCount_ = { 0, 0, 0 }; + OpInfoFailedCount_ = { 0, 0, 0 }; + + return; +} +OperatorManger::~OperatorManger() {} + +void OperatorManger::create_new_context(IRContextS* context) { + uint64_t index = *reinterpret_cast(context); + + assert(contextDependentCount_.find(index) == contextDependentCount_.end()); + + for (int i = 0; i < OperatorInfomation_.size(); i++) { + contextDependentCount_[index].push_back({ 0, 0 }); + } + + return; +} +vector OperatorManger::get_OpInfo_index(IRContextS* context, double heat) { + vector res; + vector skip; + + IRContextS OpContext = *context; + OpContext.parentIRItem_ = ERRORINDEX; + + uint64_t index = *reinterpret_cast(&OpContext); + + if (contextDependentCount_.find(index) == contextDependentCount_.end()) { + create_new_context(&OpContext); + } + + unsigned short int maxExpectIndex = ERRORINDEX; + double maxExpect = 0; + + vector>& curContextCount = contextDependentCount_[index]; + int mutateNumber = curContextCount.size(); + + for (int i = 0; i < curContextCount.size(); i++) { + pair& count = curContextCount[i]; + + unsigned int chosenNumber = count.first + count.second; + if (chosenNumber > IRINFOUPDATETHRESHOLD) { + double expect = static_cast(count.first) / (count.first + count.second); + + if (expect > maxExpect) { + maxExpectIndex = i; + maxExpect = expect; + } + } + + double tmp = get_random_double(0, 1); + if (chosenNumber < IRINFOUPDATETHRESHOLD || tmp < heat) { + res.push_back(i); + mutateNumber--; + } + else { + skip.push_back(i); + } + } + + if (maxExpectIndex == ERRORINDEX) { + for (unsigned short int i : skip) { + res.push_back(i); + } + } + else { + while (mutateNumber > 0) { + res.push_back(maxExpectIndex); + mutateNumber--; + } + } + + return res; +} +MutateOperator OperatorManger::get_operator(unsigned short int index) { + assert(index < OperatorInfomation_.size() && index >= 0); + OpInfoChosenCount_[index]++; + return OperatorInfomation_[index]; +} + +void OperatorManger::update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward) { + IRContextS OpContext = *context; + OpContext.parentIRItem_ = ERRORINDEX; + + uint64_t index = *reinterpret_cast(&OpContext); + + assert(contextDependentCount_.find(index) != contextDependentCount_.end()); + + if (item == ERRORINDEX) { + return; + } + + if (hasNewCoverage == true) { + contextDependentCount_[index][item].first += reward; + } + else { + contextDependentCount_[index][item].second += reward; + } + + return; +} + +string OperatorManger::print_OperatorInformation_status() { + unsigned long totalSuccessCount = 0; + unsigned long totalFailedCount = 0; + + string res = "Current IRTYPE: " + to_string(curIRType_) + "\n"; + + for (int i = 0; i < OperatorInfomation_.size(); i++) { + unsigned long successCount = 0; + unsigned long failedCount = 0; + MutateOperator op = OperatorInfomation_[i]; + + string OpStr = ""; + switch (op) { + case MutateOperator::moReplace: { + OpStr += "REPLACE"; + break; + } + case MutateOperator::moInsert: { + OpStr += "INSERT"; + break; + } + case MutateOperator::moDelete: { + OpStr += "DELETE"; + break; + } + } + + res += "--Operator " + OpStr + ":\n"; + res += "--Total Chosen Number: " + to_string(OpInfoChosenCount_[i]) + ", " + "Mutate Failed: " + to_string(OpInfoFailedCount_[i]) + "\n"; + + for (auto& it : contextDependentCount_) { + uint64_t context = it.first; + pair& count = it.second[i]; + + successCount += count.first; + totalSuccessCount += count.first; + failedCount += count.second; + totalFailedCount += count.second; + + res += "\tCurrent Context: " + to_string(context) + ", Successes: " + to_string(count.first) + ", Failed: " + to_string(count.second) + ", Total: " + to_string(count.first + count.second) + "\n"; + } + + res += "--Successes: " + to_string(successCount) + ", Failed: " + to_string(failedCount) + ", Total: " + to_string(successCount + failedCount) + "\n"; + } + + res += "Total Successes: " + to_string(totalSuccessCount) + ", Total Failed: " + to_string(totalFailedCount) + ", Total: " + to_string(totalSuccessCount + totalFailedCount) + "\n\n"; + + return res; +} diff --git a/src/tool.cpp b/src/tool.cpp new file mode 100755 index 0000000..67baf7f --- /dev/null +++ b/src/tool.cpp @@ -0,0 +1,1122 @@ +#include "../include/instantiate.h" + +using namespace std; + +//-----------------------------Column----------------------------- +Column::Column(name_t name, ColumnType type): identifierName_(name), columnType_(type) {} +Column::Column(Column* column) { + notNull_ = column->notNull_; + hasDefault_ = column->hasDefault_; + isVisible_ = column->isVisible_; + identifierName_ = column->identifierName_; + duplicated_ = column->duplicated_; + columnType_ = column->columnType_; + + return; +} + +void Column::instantiate() { + return; +} + +//-----------------------------Index----------------------------- +Index::Index(name_t name): identifierName_(name) {} + +//-----------------------------Constraint----------------------------- +Constraint::Constraint(name_t name, ConstraintType type): identifierName_(name), constraintType_(type) {} + +//-----------------------------Table----------------------------- +Table::Table(name_t name, IdentifierType identifierType, SelectStmtInfo* inSelectStmtInfo) : identifierName_(name), inSelectStmtInfo_(inSelectStmtInfo), identifierType_(identifierType) { + for (int i = 0; i < RESERVEDCOLUMNNAME; i++) { + acceColumnNames_.push_back(i); + } + + random_device rd; + mt19937 g(rd()); + + shuffle(acceColumnNames_.begin(), acceColumnNames_.end(), g); + + return; +} +Table::Table(Table* otherTable, SelectStmtInfo* inSelectStmtInfo) : identifierName_(otherTable->identifierName_), inSelectStmtInfo_(inSelectStmtInfo), identifierType_(otherTable->identifierType_) { + acceColumnNames_ = otherTable->acceColumnNames_; + + for (Column* c : otherTable->columns_) { + add_column(new Column(c)); + } + + return; +} +Table::~Table() { + for (Column* c : columns_) { + delete c; + } + + for (Index* i : indexes_) { + delete i; + } + + for (Constraint* c : constraints_) { + delete c; + } + + return; +} + +bool Table::check_drop_table() { + if (!refFromOtherColumns_.empty()) { + return false; + } + + return false; +} +bool Table::exist_duplicated_column() { + for (Column* c : columns_) { + if (c->duplicated_ == ColumnStatus::csDuplication) { + return true; + } + } + + return false; +} +void Table::update_duplicationInfo(vector& duplicationInfo) { + assert(duplicationInfo.size() == COLUMNNAMEMAX); + int size = columns_.size(); + + for (int i = 0; i < size; i++) { + duplicationInfo[columns_[i]->identifierName_]++; + } + + return; +} +void Table::update_duplicatedColumns(vector& duplicationInfo) { + assert(duplicationInfo.size() == COLUMNNAMEMAX); + + for (Column* c : columns_) { + assert(c->identifierName_ < COLUMNNAMEMAX); + if (duplicationInfo[c->identifierName_] > 1) { + c->duplicated_ = ColumnStatus::csDuplication; + } + else if (duplicationInfo[c->identifierName_] == 1) { + c->duplicated_ = ColumnStatus::csNormal; + } + } + + return; +} + +bool Table::column_drop_check(Column* column) { + vector indexes = get_index(column); + vector constraints = get_constraint(column); + + if (find(columns_.begin(), columns_.end(), column) == columns_.end()) { + return false; + } + + for (Index* index : indexes) { + if (index->columns_[column] == IndexType::itFunctional) { + return false; + } + } + + for (Constraint* constraint : constraints) { + if (constraint->columns_[column] == IndexType::itFunctional || constraint->constraintType_ == ConstraintType::ctForeignKey || constraint->constraintType_ == ConstraintType::ctCheck) { + return false; + } + } + + return true; +} +Column* Table::get_column() { + if (columns_.empty()) { + fprintf(stderr, "ERROR: Empty Table!!!\n"); + assert(0); + } + + return columns_[rand() % columns_.size()]; +} +Column* Table::get_column(ColumnType type) { + vector tmp; + + for (Column* c : columns_) { + if (c->columnType_ == type) { + tmp.push_back(c); + } + } + + if (tmp.empty()) { + return nullptr; + } + + return tmp[rand() % tmp.size()]; +} +name_t Table::get_acce_column_name() { + if (acceColumnNames_.empty()) { + return 0; + } + + return acceColumnNames_[0]; +} +vector Table::get_column_seq() { + int size = columns_.size(); + vector tmp; + + for (int i = 0; i < size; i++) { + tmp.push_back(columns_[i]); + } + + random_device rd; + mt19937 g(rd()); + + shuffle(tmp.begin(), tmp.end(), g); + + return tmp; +} +void Table::add_column_first(Column* column) { + assert(column != nullptr); + remove_column_name(column->identifierName_); + column->parentTable_ = this; + + columns_.insert(columns_.begin(), column); + + return; +} +bool Table::add_column(Column* column, Column* afterColumn) { + assert(column != nullptr); + remove_column_name(column->identifierName_); + column->parentTable_ = this; + + return move_column(column, afterColumn); +} +void Table::move_column_first(Column* column) { + auto it = find(columns_.begin(), columns_.end(), column); + assert(it != columns_.end()); + + columns_.erase(it); + columns_.insert(columns_.begin(), column); + + return; +} +bool Table::move_column(Column* column, Column* afterColumn) { + assert(column != afterColumn); + + auto it1 = find(columns_.begin(), columns_.end(), column); + auto it2 = find(columns_.begin(), columns_.end(), afterColumn); + + assert(afterColumn == nullptr || it2 != columns_.end()); + + if (it1 != columns_.end()) { + columns_.erase(it1); + } + + if (afterColumn == nullptr) { + columns_.push_back(column); + } + else { + auto it2 = find(columns_.begin(), columns_.end(), afterColumn); + columns_.insert(it2 + 1, column); + } + + return true; +} +bool Table::drop_column(Column* column) { + if (!column_drop_check(column)) { + return false; + } + + auto it = find(columns_.begin(), columns_.end(), column); + + add_column_name(column->identifierName_); + + drop_index(column); + drop_constraint(column); + + delete column; + columns_.erase(it); + + return true; +} + +void Table::column_rename(Column* column, name_t oldName, name_t newName) { + column->identifierName_ = newName; + + remove_column_name(newName); + add_column_name(oldName); + + return; +} + +Index* Table::get_index() { + if (indexes_.empty()) { + return nullptr; + } + + return indexes_[rand() % indexes_.size()]; +} +vector Table::get_index(Column* column) { + vector tmp; + + for (Index* index : indexes_) { + if (index->columns_.find(column) != index->columns_.end()) { + tmp.push_back(index); + } + } + + return tmp; +} +bool Table::add_index(Index* index) { + if (find(indexes_.begin(), indexes_.end(), index) != indexes_.end()) { + return false; + } + + indexes_.push_back(index); + return true; +} +bool Table::drop_index(Index* index) { + if (!index_drop_check(index)) { + return false; + } + + auto it = find(indexes_.begin(), indexes_.end(), index); + + if (index->constraint_ != nullptr) { + assert(index->constraint_->index_ == index); + index->constraint_->index_ = nullptr; + drop_constraint(index->constraint_); + } + + indexes_.erase(it); + delete index; + + return true; +} + +Constraint* Table::get_constraint() { + if (constraints_.empty()) { + return nullptr; + } + + return constraints_[rand() % constraints_.size()]; +} +vector Table::get_constraint(Column* column) { + vector tmp; + + for (Constraint* constraint : constraints_) { + if (constraint->columns_.find(column) != constraint->columns_.end()) { + tmp.push_back(constraint); + } + } + + return tmp; +} +bool Table::add_constraint(Constraint* constraint, Index* index) { + if (find(constraints_.begin(), constraints_.end(), constraint) != constraints_.end()) { + return false; + } + + constraint->index_ = index; + constraints_.push_back(constraint); + + if (index != nullptr) { + index->constraint_ = constraint; + add_index(index); + } + + if (constraint->constraintType_ == ConstraintType::ctForeignKey) { + for (auto& it : constraint->refToOtherColumns_) { + Column* otherTableColumn = it.first; + for (Column* curTableColumn : it.second) { + curTableColumn->parentTable_->set_references(curTableColumn, otherTableColumn); + } + } + } + + if (constraint->constraintType_ == ConstraintType::ctPrimaryKey) { + hasPrimaryKey_ = true; + } + + return true; +} +bool Table::drop_constraint(Constraint* constraint) { + if (!constraint_drop_check(constraint)) { + return false; + } + + auto it = find(constraints_.begin(), constraints_.end(), constraint); + + if (constraint->index_ != nullptr) { + assert(constraint->index_->constraint_ == constraint); + constraint->index_->constraint_ = nullptr; + drop_index(constraint->index_); + } + + if (constraint->constraintType_ == ConstraintType::ctForeignKey) { + for (auto& it : constraint->refToOtherColumns_) { + Column* otherTableColumn = it.first; + for (Column* curTableColumn : it.second) { + curTableColumn->parentTable_->remove_references(curTableColumn, otherTableColumn); + } + } + } + + if (constraint->constraintType_ == ConstraintType::ctPrimaryKey) { + hasPrimaryKey_ = false; + } + + delete constraint; + constraints_.erase(it); + + return true; +} +bool Table::set_references(Column* curTableColumn, Column* otherTableColumn) { + if (find(columns_.begin(), columns_.end(), curTableColumn) == columns_.end()) { + return false; + } + + if (refFromOtherColumns_.find(curTableColumn) != refFromOtherColumns_.end() && refFromOtherColumns_[curTableColumn].find(otherTableColumn) != refFromOtherColumns_[curTableColumn].end()) { + refFromOtherColumns_[curTableColumn][otherTableColumn] += 1; + } + else { + refFromOtherColumns_[curTableColumn][otherTableColumn] = 1; + } + + return true; +} +bool Table::remove_references(Column* curTableColumn, Column* otherTableColumn) { + if (find(columns_.begin(), columns_.end(), curTableColumn) == columns_.end()) { + return false; + } + + if (refFromOtherColumns_.find(curTableColumn) != refFromOtherColumns_.end() && refFromOtherColumns_[curTableColumn].find(otherTableColumn) != refFromOtherColumns_[curTableColumn].end()) { + refFromOtherColumns_[curTableColumn][otherTableColumn] -= 1; + + if (refFromOtherColumns_[curTableColumn][otherTableColumn] <= 0) { + auto it1 = refFromOtherColumns_[curTableColumn].find(otherTableColumn); + refFromOtherColumns_[curTableColumn].erase(it1); + + if (refFromOtherColumns_[curTableColumn].empty()) { + auto it2 = refFromOtherColumns_.find(curTableColumn); + refFromOtherColumns_.erase(it2); + } + } + } + else { + return false; + } + + return true; +} + + +bool Table::remove_column_name(name_t name) { + auto it = find(acceColumnNames_.begin(), acceColumnNames_.end(), name); + + if (it == acceColumnNames_.end()) { + return false; + } + + acceColumnNames_.erase(it); + + return true; +} +bool Table::add_column_name(name_t name) { + auto it = find(acceColumnNames_.begin(), acceColumnNames_.end(), name); + if (it == acceColumnNames_.end()) { + acceColumnNames_.push_back(name); + return true; + } + + return false; +} +void Table::drop_index(Column* column) { + vector waitForDrop; + vector indexes = get_index(column); + + for (Index* index : indexes) { + auto it = index->columns_.find(column); + index->columns_.erase(it); + + if (index->columns_.empty()) { + waitForDrop.push_back(index); + } + } + + for (Index* index : waitForDrop) { + drop_index(index); + } + + return; +} +void Table::drop_constraint(Column* column) { + vector waitForDrop; + vector constraints = get_constraint(column); + + for (Constraint* constraint : constraints) { + auto it = constraint->columns_.find(column); + constraint->columns_.erase(column); + + if (constraint->columns_.empty()) { + waitForDrop.push_back(constraint); + } + } + + for (Constraint* constraint : constraints_) { + drop_constraint(constraint); + } + + return; +} + +bool Table::index_drop_check(Index* index) { + if (find(indexes_.begin(), indexes_.end(), index) == indexes_.end()) { + return false; + } + + for (auto& it : index->columns_) { + if (refFromOtherColumns_.find(it.first) != refFromOtherColumns_.end()) { + return false; + } + } + + return true; +} + +bool Table::constraint_drop_check(Constraint* constraint) { + if (find(constraints_.begin(), constraints_.end(), constraint) == constraints_.end()) { + return false; + } + + return true; +} + +//-----------------------------SelectStmtInfo----------------------------- +SelectStmtInfo::SelectStmtInfo(StmtLocation location, int rowNumber, int columnNumber) : location_(location), rowNumber_(rowNumber), columnNumber_(columnNumber) {} +SelectStmtInfo::~SelectStmtInfo() { + clear_local_info(); + clear_cte(); + + return; +} + +bool SelectStmtInfo::is_duplicated_table(Table* table) { + for (Table* t : usedTables_) { + if (t->identifierName_ == table->identifierName_) { + return true; + } + } + + return false; +} +bool SelectStmtInfo::exist_duplicated_column(vector& v1, vector& v2) { + vector bitmap = vector(COLUMNNAMEMAX, 0); + + for (Column* c : v1) { + bitmap[c->identifierName_]++; + } + + for (Column* c : v2) { + bitmap[c->identifierName_]++; + } + + for (int i : bitmap) { + if (i > 1) { + return true; + } + } + + return false; +} +bool SelectStmtInfo::has_column_limit() { + return columnNumber_ != DEFAULTCOLUMNNUMBER; +} +bool SelectStmtInfo::has_row_limit() { + return rowNumber_ != DEFAULTROWNUMBER; +} + +void SelectStmtInfo::add_used_table(Table* table) { + table->update_duplicationInfo(duplicationInfo_); + usedTables_.push_back(table); + + return; +} +void SelectStmtInfo::clear_local_info() { + for (Table* t : usedTables_) { + delete t; + } + + for (int i = 0; i < COLUMNNAMEMAX; i++) { + duplicationInfo_[i] = 0; + } + + hasAggregate = false; + + usedTables_.clear(); + usedInnerColumns_.clear(); + acceColumns_.clear(); + windowStatusRecord_.clear(); + + return; +} +void SelectStmtInfo::clear_cte() { + for (auto it = innerCteTables_.begin(); it != innerCteTables_.end(); it++) { + Table* cte = *it; + delete cte; + } + + innerCteTables_.clear(); + + return; +} + +void SelectStmtInfo::update_acceColumns() { + acceColumns_.clear(); + map> tmp; + + for (Table* t : usedTables_) { + t->update_duplicatedColumns(duplicationInfo_); + + for (Column* c : t->columns_) { + tmp[c->identifierName_].push_back(c); + } + } + + for (Column* c : outReferences_) { + if (tmp.find(c->identifierName_) == tmp.end()) { + tmp[c->identifierName_].push_back(c); + } + else { + Column* cc = tmp[c->identifierName_][0]; + + if (cc->parentTable_->inSelectStmtInfo_ != this) { + tmp[c->identifierName_].push_back(c); + } + } + } + + for (auto& it : tmp) { + for (Column* c : it.second) { + acceColumns_.push_back(c); + } + } + + return; +} +void SelectStmtInfo::update_acceColumns(vector& usedTables, vector& duplicationInfo) { + acceColumns_.clear(); + map> tmp; + + for (Table* t : usedTables) { + t->update_duplicatedColumns(duplicationInfo); + + for (Column* c: t->columns_) { + tmp[c->identifierName_].push_back(c); + } + } + + for (Column* c : outReferences_) { + if (tmp.find(c->identifierName_) == tmp.end()) { + tmp[c->identifierName_].push_back(c); + } + else { + Column* cc = tmp[c->identifierName_][0]; + + if (cc->parentTable_->inSelectStmtInfo_ != this) { + tmp[c->identifierName_].push_back(c); + } + } + } + + for (auto& it : tmp) { + for (Column* c : it.second) { + acceColumns_.push_back(c); + } + } + + return; +} + +void SelectStmtInfo::add_usedInnerColumns(Column* column) { + if (find(usedInnerColumns_.begin(), usedInnerColumns_.end(), column) == usedInnerColumns_.end()) { + usedInnerColumns_.push_back(column); + } + + return; +} +void SelectStmtInfo::add_usedOutColumns(Column* column) { + if (find(usedOutColumns_.begin(), usedOutColumns_.end(), column) == usedOutColumns_.end()) { + usedOutColumns_.push_back(column); + } + + return; +} +void SelectStmtInfo::add_out_usedColumns(vector& usedColumns) { + for (Column* c : usedColumns) { + if (c->parentTable_->inSelectStmtInfo_ != this) { + add_usedOutColumns(c); + } + } + + return; +} +void SelectStmtInfo::add_all_usedColumns(vector& usedColumns) { + for (Column* c : usedColumns) { + if (c->parentTable_->inSelectStmtInfo_ == this) { + add_usedInnerColumns(c); + } + else { + add_usedOutColumns(c); + } + } + + return; +} + +//-----------------------------GlobalStatusManger----------------------------- +GlobalStatusManger::~GlobalStatusManger() { + for (Table* t : globalTables_) { + delete t; + } + + return; +} + +void GlobalStatusManger::reset_status() { + totalTableName_ = 0; + totalViewName_ = 0; + totalWindowName_ = 0; + totalIndexName_ = 0; + totalConstraintName_ = 0; + + assert(selectInfoStack_.empty()); + + for (Table* t : globalTables_) { + delete t; + } + + globalTables_.clear(); + + return; +} + +void GlobalStatusManger::push_selectInfo(StmtLocation location, int rowNumber, int columnNumber) { + SelectStmtInfo* info = new SelectStmtInfo(location, rowNumber, columnNumber); + SelectStmtInfo* preInfo = get_cur_selectInfo(); + + if (preInfo != nullptr) { + info->outCteTables_ = preInfo->outCteTables_; + for (Table* t : preInfo->innerCteTables_) { + info->outCteTables_.push_back(t); + } + + info->outReferences_ = preInfo->acceColumns_; + + if (location == StmtLocation::slRecursiveCTE) { + info->recursiveCteName_ = preInfo->recursiveCteName_; + } + } + + selectInfoStack_.push(info); + + return; +} +void GlobalStatusManger::pop_selectInfo() { + SelectStmtInfo* info = get_cur_selectInfo(); + pop_cur_selectInfo(); + SelectStmtInfo* preinfo = get_cur_selectInfo(); + + if (preinfo != nullptr && info != nullptr) { + if (find(ignoreInnerUsedColumns_.begin(), ignoreInnerUsedColumns_.end(), info->location_) != ignoreInnerUsedColumns_.end()) { + preinfo->add_out_usedColumns(info->usedOutColumns_); + } + else { + preinfo->add_all_usedColumns(info->usedOutColumns_); + } + } + + if (info != nullptr) { + delete info; + } + + return; +} + +SelectStmtInfo* GlobalStatusManger::get_cur_selectInfo() { + if (selectInfoStack_.empty()) { + return nullptr; + } + + return selectInfoStack_.top(); +} +void GlobalStatusManger::pop_cur_selectInfo() { + if (selectInfoStack_.empty()) { + fprintf(stderr, "ERROR: Pop Empty Stack\n"); + assert(0); + } + + selectInfoStack_.pop(); + + return; +} + +int GlobalStatusManger::get_acce_table_number() { + int res = 0; + SelectStmtInfo* info = get_cur_selectInfo(); + + res += globalTables_.size() + info->outCteTables_.size() + info->innerCteTables_.size(); + + return res; +} +Table* GlobalStatusManger::get_acce_table(int index) { + Table* res = nullptr; + SelectStmtInfo* info = get_cur_selectInfo(); + + if (index < globalTables_.size()) { + res = globalTables_[index]; + } + else if(index - globalTables_.size() < info->outCteTables_.size()) { + res = info->outCteTables_[index - globalTables_.size()]; + } + else { + res = info->innerCteTables_[index - globalTables_.size() - info->outCteTables_.size()]; + } + + assert(res != nullptr); + + return res; +} +vector GlobalStatusManger::get_acce_table(IdentifierType type) { + assert(type == IdentifierType::iTable || type == IdentifierType::iView); + + vector res; + + for (Table* table : globalTables_) { + if (table->identifierType_ == type) { + res.push_back(table); + } + } + + return res; +} + +name_t GlobalStatusManger::get_new_table_name() { + return totalTableName_++; +} +name_t GlobalStatusManger::get_new_view_name() { + return totalViewName_++; +} +name_t GlobalStatusManger::get_new_window_name() { + return totalWindowName_++; +} +name_t GlobalStatusManger::get_new_index_name() { + return totalIndexName_++; +} +name_t GlobalStatusManger::get_new_constraint_name() { + return totalConstraintName_++; +} + +bool GlobalStatusManger::add_table(Table* table) { + if (table == nullptr || find(globalTables_.begin(), globalTables_.end(), table) != globalTables_.end()) { + return false; + } + + globalTables_.push_back(table); + + return true; +} +bool GlobalStatusManger::drop_table(Table* table) { + auto it = find(globalTables_.begin(), globalTables_.end(), table); + + if (it == globalTables_.end()) { + return false; + } + + globalTables_.erase(it); + delete table; + + return true; +} +bool GlobalStatusManger::drop_table(name_t name, IdentifierType type) { + Table* tmp = nullptr; + + for (Table* table : globalTables_) { + if (table->identifierName_ == name && table->identifierType_ == type) { + tmp = table; + break; + } + } + + if (tmp != nullptr) { + return drop_table(tmp); + } + + return true; +} + +//-----------------------------IRTrim----------------------------- +IRTrim::IRTrim(Instantiator* instantiator): instantiator_(instantiator) { + instantiate_simple_limit(); + instantiate_simple_column_list(); + instantiate_simple_alias(); + instantiate_simple_expr_root(); + instantiate_simple_expr_root_true(); + instantiate_simple_expr_root_list(); + instantiate_simple_simple_select_item_list(); + instantiate_simple_window_spec(); + instantiate_simple_index_name(); + instantiate_simple_constraint_name(); + instantiate_simple_key_part(); + instantiate_simple_key_part_list(); + instantiate_simple_table_element(); + instantiate_simple_values(); + + return; +} +IRTrim::~IRTrim() { + for (IR* ir : simpleIR_) { + if (ir != nullptr) { + deep_delete(ir); + } + } + + return; +} + +void IRTrim::instantiate_simple_limit() { + IR* iconst = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); + IR* limit_options = new IR(IRTYPE::kLimitOptions, OP0(), iconst, nullptr); + IR* limit_clause = new IR(IRTYPE::kLimitClause, OP3(TERMINAL::tLimit, TERMINAL::tEmpty, TERMINAL::tEmpty), limit_options, nullptr); + + simple_limit_ = limit_clause; + simpleIR_.push_back(simple_limit_); + + return; +} +void IRTrim::instantiate_simple_column_list() { + IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), ident, nullptr); + IR* column_list = new IR(IRTYPE::kColumnList, OP0(), column_name, nullptr); + + simple_column_list_ = column_list; + simpleIR_.push_back(simple_column_list_); + + return; +} +void IRTrim::instantiate_simple_alias() { + IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* alias = new IR(IRTYPE::kAlias, OP0(), ident, nullptr); + + simple_alias_ = alias; + simpleIR_.push_back(simple_alias_); + + return; +} +void IRTrim::instantiate_simple_expr_root() { + IR* iconst = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); + IR* simple_expr = new IR(IRTYPE::kSimpleExpr, OP0(), iconst, nullptr); + IR* bit_expr = new IR(IRTYPE::kBitExpr, OP0(), simple_expr, nullptr); + IR* predicate = new IR(IRTYPE::kPredicate, OP0(), bit_expr, nullptr); + IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), predicate, nullptr); + IR* expr = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); + IR* expr_root = new IR(IRTYPE::kExprRoot, OP0(), expr, nullptr); + + iconst->long_val_ = 1; + + simple_expr_root_ = expr_root; + simpleIR_.push_back(simple_expr_root_); + + return; +} +void IRTrim::instantiate_simple_expr_root_true() { + IR* literal = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tTrue, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + IR* simple_expr = new IR(IRTYPE::kSimpleExpr, OP0(), literal, nullptr); + IR* bit_expr = new IR(IRTYPE::kBitExpr, OP0(), simple_expr, nullptr); + IR* predicate = new IR(IRTYPE::kPredicate, OP0(), bit_expr, nullptr); + IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), predicate, nullptr); + IR* expr = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); + IR* expr_root = new IR(IRTYPE::kExprRoot, OP0(), expr, nullptr); + + simple_expr_root_true_ = expr_root; + simpleIR_.push_back(simple_expr_root_true_); + + return; +} +void IRTrim::instantiate_simple_expr_root_list() { + IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); + IR* columnref = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), column_name, nullptr); + IR* simple_expr = new IR(IRTYPE::kSimpleExpr, OP0(), columnref, nullptr); + IR* bit_expr = new IR(IRTYPE::kBitExpr, OP0(), simple_expr, nullptr); + IR* predicate = new IR(IRTYPE::kPredicate, OP0(), bit_expr, nullptr); + IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), predicate, nullptr); + IR* expr = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); + IR* exor_root = new IR(IRTYPE::kExprRoot, OP0(), expr, nullptr); + IR* expr_root_list = new IR(IRTYPE::kExprRootList, OP0(), exor_root, nullptr); + + simple_expr_root_list_ = expr_root_list; + simpleIR_.push_back(simple_expr_root_list_); + + return; +} +void IRTrim::instantiate_simple_simple_select_item_list() { + IR* expr_root = deep_copy(simple_expr_root_); + IR* alise = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), deep_copy(simple_alias_), nullptr); + IR* select_item = new IR(IRTYPE::kSelectItem, OP0(), expr_root, alise); + IR* select_item_list = new IR(IRTYPE::kSelectItemList, OP0(), select_item, nullptr); + + simple_select_item_list_ = select_item_list; + simpleIR_.push_back(simple_select_item_list_); + + return; +} +void IRTrim::instantiate_simple_window_spec() { + IR* opt_existing_window_name = new IR(IRTYPE::kOptExistingWindowName, OP0(), nullptr, nullptr); + IR* opt_partition_clause = new IR(IRTYPE::kOptPartitionClause, OP0(), nullptr, nullptr); + IR* opt_window_order_by_clause = new IR(IRTYPE::kOptWindowOrderByClause, OP0(), nullptr, nullptr); + IR* opt_window_frame_clause = new IR(IRTYPE::kOptWindowFrameClause, OP0(), nullptr, nullptr); + + IR* tmp1 = new IR(IRTYPE::kWindowSpecDetailsTmp1, OP0(), opt_window_order_by_clause, opt_window_frame_clause); + IR* tmp2 = new IR(IRTYPE::kWindowSpecDetailsTmp2, OP0(), opt_partition_clause, tmp1); + IR* window_spec_details = new IR(IRTYPE::kWindowSpecDetails, OP0(), opt_existing_window_name, tmp2); + + IR* window_spec = new IR(IRTYPE::kWindowSpec, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), window_spec_details, nullptr); + + simple_window_spec_ = window_spec; + simpleIR_.push_back(simple_window_spec_); + + return; +} +void IRTrim::instantiate_simple_index_name() { + IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* index_name = new IR(IRTYPE::kIndexName, OP0(), ident, nullptr); + + simple_index_name_ = index_name; + simpleIR_.push_back(simple_index_name_); + + return; +} +void IRTrim::instantiate_simple_constraint_name() { + IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* constraint_name = new IR(IRTYPE::kConstraintName, OP0(), ident, nullptr); + + simple_constraint_name_ = constraint_name; + simpleIR_.push_back(simple_constraint_name_); + + return; +} +void IRTrim::instantiate_simple_key_part() { + IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), ident, nullptr); + IR* opt_ordering_direction = new IR(IRTYPE::kOptOrderingDirection, OP0(), nullptr, nullptr); + IR* key_part = new IR(IRTYPE::kKeyPart, OP0(), column_name, opt_ordering_direction); + + simple_key_part_ = key_part; + simpleIR_.push_back(simple_key_part_); + + return; +} +void IRTrim::instantiate_simple_key_part_list() { + IR* key_part = deep_copy(simple_key_part_); + IR* key_list = new IR(IRTYPE::kKeyList, OP0(), key_part, nullptr); + + simple_key_part_list_ = key_list; + simpleIR_.push_back(simple_key_part_list_); + + return; +} +void IRTrim::instantiate_simple_table_element() { + IR* int_type = new IR(IRTYPE::kIntType, OP3(TERMINAL::tInt, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + IR* opt_field_options = new IR(IRTYPE::kOptFieldOptions, OP0(), nullptr, nullptr); + IR* number_type = new IR(IRTYPE::kNumberType, OP0(), int_type, opt_field_options); + IR* data_type = new IR(IRTYPE::kDataType, OP0(), number_type, nullptr); + IR* opt_column_attribute_list = new IR(IRTYPE::kOptColumnAttributeList, OP0(), nullptr, nullptr); + IR* field_def = new IR(IRTYPE::kFieldDef, OP0(), data_type, opt_column_attribute_list); + + IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), ident, nullptr); + IR* column_def = new IR(IRTYPE::kColumnDef, OP0(), column_name, field_def); + + IR* table_element = new IR(IRTYPE::kTableElement, OP0(), column_def, nullptr); + + simple_table_element_ = table_element; + simpleIR_.push_back(simple_table_element_); + + return; +} +void IRTrim::instantiate_simple_values() { + IR* expr_or_default = new IR(IRTYPE::kExprOrDefault, OP3(TERMINAL::tDefault, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + IR* values = new IR(IRTYPE::kValues, OP0(), expr_or_default, nullptr); + + simple_values_ = values; + simpleIR_.push_back(simple_values_); + + return; +} + +IR* IRTrim::get_expr_root_columnref(Column* column) { + IR* tmp1 = nullptr; + + if (column->duplicated_ == ColumnStatus::csDuplication) { + IR* table_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* table_name = new IR(IRTYPE::kTableName, OP0(), table_ident, nullptr); + + instantiator_->instantiate_ident(table_name, IdentifierType::iTable, column->parentTable_->identifierName_); + + IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); + + instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); + + tmp1 = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tOpDot, TERMINAL::tEmpty), table_name, column_name); + } + else { + IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); + + instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); + + tmp1 = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), column_name, nullptr); + } + + IR* tmp2 = new IR(IRTYPE::kSimpleExpr, OP0(), tmp1, nullptr); + IR* tmp3 = new IR(IRTYPE::kBitExpr, OP0(), tmp2, nullptr); + IR* tmp4 = new IR(IRTYPE::kPredicate, OP0(), tmp3, nullptr); + IR* tmp5 = new IR(IRTYPE::kBoolPri, OP0(), tmp4, nullptr); + IR* tmp6 = new IR(IRTYPE::kExpr, OP0(), tmp5, nullptr); + IR* tmp7 = new IR(IRTYPE::kExprRoot, OP0(), tmp6, nullptr); + + return tmp7; +} +void IRTrim::set_recursive_limit(IR* expr_root) { + IR* number_tmp1 = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); + number_tmp1->long_val_ = rand() % LIMITMAX; + + IR* number_tmp2 = new IR(IRTYPE::kSimpleExpr, OP0(), number_tmp1, nullptr); + IR* number_tmp3 = new IR(IRTYPE::kBitExpr, OP0(), number_tmp2, nullptr); + IR* number_tmp4 = new IR(IRTYPE::kPredicate, OP0(), number_tmp3, nullptr); + + + IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); + IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); + + instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, RESERVEDCOLUMNNAME); + + IR* tmp1 = new IR(IRTYPE::kColumnref, OP0(), column_name, nullptr); + IR* tmp2 = new IR(IRTYPE::kSimpleExpr, OP0(), tmp1, nullptr); + IR* tmp3 = new IR(IRTYPE::kBitExpr, OP0(), tmp2, nullptr); + IR* tmp4 = new IR(IRTYPE::kPredicate, OP0(), tmp3, nullptr); + IR* tmp5 = new IR(IRTYPE::kBoolPri, OP0(), tmp4, nullptr); + + IR* comp_op = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpLessthan, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); + + IR* bool_pri_tmp1 = new IR(IRTYPE::kBoolPriTmp1, OP0(), comp_op, number_tmp4); + IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), tmp5, bool_pri_tmp1); + + IR* expr_right = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); + IR* expr_left = NT_check(expr_root->left_, IRTYPE::kExpr); + + IR* new_expr = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), expr_left, expr_right); + + expr_root->left_ = new_expr; + + return; +} \ No newline at end of file -- Gitee From 3a55f8c5eec5d5321ca14ac14fdda282163d553c Mon Sep 17 00:00:00 2001 From: PengJiaScu Date: Thu, 16 Nov 2023 07:59:02 +0000 Subject: [PATCH 4/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20incl?= =?UTF-8?q?ude?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ast.h | 1806 ----------------------------------------- include/connector.h | 44 - include/define.h | 797 ------------------ include/instantiate.h | 459 ----------- include/mutate.h | 207 ----- 5 files changed, 3313 deletions(-) delete mode 100755 include/ast.h delete mode 100755 include/connector.h delete mode 100755 include/define.h delete mode 100755 include/instantiate.h delete mode 100755 include/mutate.h diff --git a/include/ast.h b/include/ast.h deleted file mode 100755 index ea406eb..0000000 --- a/include/ast.h +++ /dev/null @@ -1,1806 +0,0 @@ -#ifndef __AST_H__ -#define __AST_H__ -#include -#include -#include "define.h" -#include - -using namespace std; - -enum IRTYPE{ -#define DECLARE_TYPE(v) \ - v, -ALLTYPE(DECLARE_TYPE) -#undef DECLARE_TYPE -}; - -enum TERMINAL { -#define DECLARE_TERMINAL(v) \ - v, -ALLTERMINAL(DECLARE_TERMINAL) -#undef DECLARE_TERMINAL -}; - -#define DECLARE_CLASS(v) \ - class v ; -ALLCLASS(DECLARE_CLASS); -#undef DECLARE_CLASS - -enum CASEIDX{ - CASE0, CASE1, CASE2, CASE3, CASE4, CASE5, CASE6, CASE7, CASE8, - CASE9, CASE10, CASE11, CASE12, CASE13, CASE14, CASE15, CASE16, - CASE17, CASE18, CASE19, CASE20, CASE21, CASE22, CASE23, CASE24, - CASE25, CASE26, CASE27, CASE28, CASE29, CASE30, CASE31, CASE32, - CASE33, CASE34, CASE35, CASE36, CASE37, CASE38, CASE39, CASE40, - CASE41, CASE42, CASE43, CASE44, CASE45, CASE46, CASE47, CASE48, - CASE49, CASE50, CASE51, CASE52, CASE53, CASE54, CASE55, CASE56, - CASE57, CASE58, CASE59, CASE60, CASE61, CASE62, CASE63 -}; - -class IROperator{ -public: - IROperator(TERMINAL prefix, TERMINAL middle, TERMINAL suffix): - prefix_(prefix), middle_(middle), suffix_(suffix) {} - - TERMINAL prefix_; - TERMINAL middle_; - TERMINAL suffix_; -}; - -class IR{ -public: - IR(IRTYPE type, IROperator * op, IR * left, IR* right): type_(type), op_(op), left_(left), right_(right) {} - - IR(const IR* ir, IR* left, IR* right){ - this->type_ = ir->type_; - - if(ir->op_ != NULL) - this->op_ = OP3(ir->op_->prefix_, ir->op_->middle_, ir->op_->suffix_); - else - this->op_ = OP3(tEmpty, tEmpty, tEmpty); - - this->left_ = left; - this->right_ = right; - - this->str_val_ = ir->str_val_; - this->long_val_ = ir->long_val_; - } - - union{ - int int_val_; - long long_val_; - double float_val_; - bool bool_val_; - }; - - IRTYPE type_; - - string str_val_; - - IROperator* op_; - IR* left_; - IR* right_; - - string to_string(); - string to_string_core(); - void trim_string(string&); -}; - -class Node{ -public: - Node(){}; - ~Node(){}; - - char length_; - unsigned long int vector_; - - unsigned int case_idx_; - - virtual IR* translate() {}; - virtual void deep_delete() {}; -}; - -IR * deep_copy(const IR * root); -void deep_delete(IR * root); - -class ParseToplevel: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Stmtmulti* stmtmulti_; -}; - -class Stmtmulti: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Stmtmulti* stmtmulti_; - Stmt* stmt_; -}; - -class Stmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - CreateTableStmt* create_table_stmt_; - CreateViewStmt* create_view_stmt_; - CreateIndexStmt* create_index_stmt_; - SelectStmt* select_stmt_; - DropIndexStmt* drop_index_stmt_; - DropTableStmt* drop_table_stmt_; - DropViewStmt* drop_view_stmt_; - DeleteStmt* delete_stmt_; - UpdateStmt* update_stmt_; - InsertStmt* insert_stmt_; - AlterTableStmt* alter_table_stmt_; -}; - -class DeleteStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptSimpleLimit* opt_simple_limit_; - OptOrderClause* opt_order_clause_; - OptWhereClause* opt_where_clause_; - OptAlias* opt_alias_; - TableName* table_name_; - OptDeleteOptions* opt_delete_options_; - OptWithClause* opt_with_clause_; - TableReferenceList* table_reference_list_; - TableList* table_list_; -}; - -class OptDeleteOptions: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - DeleteOptions* delete_options_; -}; - -class DeleteOptions: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - DeleteOption* delete_option_; - DeleteOptions* delete_options_; -}; - -class DeleteOption: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class AlterTableStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - AlterList* alter_list_; - TableName* table_name_; -}; - -class AlterList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - AlterListItem* alter_list_item_; - AlterList* alter_list_; -}; - -class AlterListItem: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptPlace* opt_place_; - FieldDef* field_def_; - ColumnName* column_name_1_; - ColumnName* column_name_2_; - TableElementList* table_element_list_; - TableConstraintDef* table_constraint_def_; - ConstraintName* constraint_name_; - IndexName* index_name_1_; - IndexName* index_name_2_; - ExprRoot* expr_root_; - Visibility* visibility_; - TableName* table_name_; -}; - -class OptPlace: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnName* column_name_; -}; - -class DropIndexStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableName* table_name_; - IndexName* index_name_; -}; - -class DropTableStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableList* table_list_; - IfExists* if_exists_; -}; - -class IfExists: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class TableList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableName* table_name_; - TableList* table_list_; -}; - -class DropViewStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableList* table_list_; - IfExists* if_exists_; -}; - -class UpdateStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptSimpleLimit* opt_simple_limit_; - OptOrderClause* opt_order_clause_; - OptWhereClause* opt_where_clause_; - UpdateList* update_list_; - TableReferenceList* table_reference_list_; - OptIgnore* opt_ignore_; - OptLowPriority* opt_low_priority_; - OptWithClause* opt_with_clause_; -}; - -class OptSimpleLimit: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Iconst* iconst_; -}; - -class OptWithClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WithClause* with_clause_; -}; - -class OptLowPriority: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class InsertStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptInsertUpdateList* opt_insert_update_list_; - OptValuesReference* opt_values_reference_; - InsertFromConstructor* insert_from_constructor_; - TableName* table_name_; - OptIgnore* opt_ignore_; - InsertLockOption* insert_lock_option_; - UpdateList* update_list_; - InsertQueryExpression* insert_query_expression_; -}; - -class InsertQueryExpression: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryExpression* query_expression_; - ColumnList* column_list_; -}; - -class InsertFromConstructor: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ValuesList* values_list_; - ColumnList* column_list_; -}; - -class ValuesList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - RowValue* row_value_; - ValuesList* values_list_; -}; - -class RowValue: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptValues* opt_values_; -}; - -class OptValues: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Values* values_; -}; - -class Values: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprOrDefault* expr_or_default_; - Values* values_; -}; - -class ExprOrDefault: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; -}; - -class OptValuesReference: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptColumnList* opt_column_list_; - TableName* table_name_; -}; - -class OptInsertUpdateList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - UpdateList* update_list_; -}; - -class UpdateList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - UpdateElem* update_elem_; - UpdateList* update_list_; -}; - -class UpdateElem: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprOrDefault* expr_or_default_; - Columnref* columnref_; -}; - -class InsertLockOption: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptIgnore: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class CreateIndexStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - KeyListWithExpression* key_list_with_expression_; - TableName* table_name_; - IndexName* index_name_; - OptUnique* opt_unique_; -}; - -class OptUnique: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class CreateViewStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryExpression* query_expression_; - OptColumnList* opt_column_list_; - ViewName* view_name_; - OptViewAlgorithm* opt_view_algorithm_; - OptOrReplace* opt_or_replace_; -}; - -class OptOrReplace: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptViewAlgorithm: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class CreateTableStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptDuplicateAsQe* opt_duplicate_as_qe_; - TableElementList* table_element_list_; - TableName* table_name_; - OptIfNotExists* opt_if_not_exists_; - OptTemporary* opt_temporary_; - DuplicateAsQe* duplicate_as_qe_; -}; - -class OptTemporary: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptIfNotExists: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptDuplicateAsQe: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - DuplicateAsQe* duplicate_as_qe_; -}; - -class DuplicateAsQe: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryExpression* query_expression_; - Duplicate* duplicate_; -}; - -class Duplicate: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class TableElementList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableElement* table_element_; - TableElementList* table_element_list_; -}; - -class TableElement: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnDef* column_def_; - TableConstraintDef* table_constraint_def_; -}; - -class ColumnDef: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - FieldDef* field_def_; - ColumnName* column_name_; -}; - -class FieldDef: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptColumnAttributeList* opt_column_attribute_list_; - DataType* data_type_; -}; - -class DataType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - NumberType* number_type_; - BoolType* bool_type_; - StringType* string_type_; -}; - -class StringType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptFieldLength* opt_field_length_; - FieldLength* field_length_; -}; - -class BoolType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class NumberType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptFieldOptions* opt_field_options_; - IntType* int_type_; - OptPrecision* opt_precision_; - RealType* real_type_; - FloatOptions* float_options_; - NumericType* numeric_type_; -}; - -class NumericType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class RealType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptPrecision: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Precision* precision_; -}; - -class IntType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptFieldOptions: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - FieldOptionList* field_option_list_; -}; - -class FieldOptionList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - FieldOption* field_option_; - FieldOptionList* field_option_list_; -}; - -class FieldOption: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptColumnAttributeList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnAttributeList* column_attribute_list_; -}; - -class ColumnAttributeList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnAttribute* column_attribute_; - ColumnAttributeList* column_attribute_list_; -}; - -class ColumnAttribute: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - NotNull* not_null_; - DefaultAttribute* default_attribute_; - Visibility* visibility_; -}; - -class DefaultAttribute: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; -}; - -class NotNull: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class Visibility: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptConstraintName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ConstraintName* constraint_name_; -}; - -class CheckConstraint: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; -}; - -class TableConstraintDef: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - KeyListWithExpression* key_list_with_expression_; - OptIndexName* opt_index_name_; - ConstraintKeyType* constraint_key_type_; - OptConstraintName* opt_constraint_name_; - CheckConstraint* check_constraint_; - References* references_; - KeyList* key_list_; -}; - -class References: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptOnUpdateDelete* opt_on_update_delete_; - ColumnList* column_list_; - TableName* table_name_; -}; - -class OptOnUpdateDelete: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OnUpdateOption* on_update_option_1_; - OnUpdateOption* on_update_option_2_; -}; - -class OnUpdateOption: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class KeyList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - KeyPart* key_part_; - KeyList* key_list_; -}; - -class KeyListWithExpression: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - KeyPartWithExpression* key_part_with_expression_; - KeyListWithExpression* key_list_with_expression_; -}; - -class KeyPartWithExpression: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - KeyPart* key_part_; - OptOrderingDirection* opt_ordering_direction_; - ExprRoot* expr_root_; -}; - -class KeyPart: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptOrderingDirection* opt_ordering_direction_; - ColumnName* column_name_; - Iconst* iconst_; -}; - -class ConstraintKeyType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptIndexName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - IndexName* index_name_; -}; - -class SelectStmt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryExpression* query_expression_; -}; - -class QueryExpression: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptLimitClause* opt_limit_clause_; - OptOrderClause* opt_order_clause_; - QueryExpressionBody* query_expression_body_; - WithClause* with_clause_; -}; - -class QueryExpressionBody: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryPrimary* query_primary_; - QueryExpressionParens* query_expression_parens_; - QueryExpressionBody* query_expression_body_1_; - QueryExpressionBody* query_expression_body_2_; - OptUnionOption* opt_union_option_; -}; - -class QueryPrimary: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QuerySpecification* query_specification_; -}; - -class QuerySpecification: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptWindowClause* opt_window_clause_; - OptHavingClause* opt_having_clause_; - OptGroupClause* opt_group_clause_; - OptWhereClause* opt_where_clause_; - OptFromClause* opt_from_clause_; - SelectItemList* select_item_list_; - OptSelectOptions* opt_select_options_; -}; - -class OptWindowClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowDefinitionList* window_definition_list_; -}; - -class WindowDefinitionList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowDefinition* window_definition_; - WindowDefinitionList* window_definition_list_; -}; - -class WindowDefinition: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowSpec* window_spec_; - WindowName* window_name_; -}; - -class WindowSpec: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowSpecDetails* window_spec_details_; -}; - -class WindowSpecDetails: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptWindowFrameClause* opt_window_frame_clause_; - OptWindowOrderByClause* opt_window_order_by_clause_; - OptPartitionClause* opt_partition_clause_; - OptExistingWindowName* opt_existing_window_name_; -}; - -class OptExistingWindowName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowName* window_name_; -}; - -class OptPartitionClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRootList* expr_root_list_; -}; - -class OptWindowOrderByClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OrderList* order_list_; -}; - -class OrderList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OrderExpr* order_expr_; - OrderList* order_list_; -}; - -class OrderExpr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptOrderingDirection* opt_ordering_direction_; - ExprRoot* expr_root_; -}; - -class OptOrderingDirection: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptWindowFrameClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowFrameExtent* window_frame_extent_; - WindowFrameUnits* window_frame_units_; -}; - -class WindowFrameUnits: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class WindowFrameExtent: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowFrameStart* window_frame_start_; - WindowFrameBetween* window_frame_between_; -}; - -class WindowFrameStart: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Iconst* iconst_; -}; - -class WindowFrameBetween: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowFrameBound* window_frame_bound_; - WindowFrameStart* window_frame_start_; -}; - -class WindowFrameBound: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowFrameStart* window_frame_start_; - Iconst* iconst_; -}; - -class OptHavingClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; -}; - -class OptGroupClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OlapOpt* olap_opt_; - ExprRootList* expr_root_list_; -}; - -class OlapOpt: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptWhereClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WhereClause* where_clause_; -}; - -class WhereClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; -}; - -class OptFromClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - FromClause* from_clause_; -}; - -class FromClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableReferenceList* table_reference_list_; -}; - -class TableReferenceList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableReference* table_reference_; - TableReferenceList* table_reference_list_; -}; - -class TableReference: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableFactor* table_factor_; - JoinedTable* joined_table_; -}; - -class TableFactor: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - SingleTable* single_table_; - DerivedTable* derived_table_; - JoinedTableParens* joined_table_parens_; - TableReferenceListParens* table_reference_list_parens_; -}; - -class TableReferenceListParens: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableReferenceList* table_reference_list_; - TableReference* table_reference_; -}; - -class JoinedTableParens: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - JoinedTable* joined_table_; -}; - -class DerivedTable: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptColumnList* opt_column_list_; - Alias* alias_; - Subquery* subquery_; -}; - -class OptColumnList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnList* column_list_; -}; - -class ColumnList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnName* column_name_; - ColumnList* column_list_; -}; - -class Subquery: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryExpressionParens* query_expression_parens_; -}; - -class SingleTable: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptAlias* opt_alias_; - TableName* table_name_; -}; - -class OptAlias: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Alias* alias_; -}; - -class JoinedTable: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; - TableReference* table_reference_1_; - TableReference* table_reference_2_; - InnerJoinType* inner_join_type_; - ColumnList* column_list_; - OuterJoinType* outer_join_type_; - TableFactor* table_factor_; - NaturalJoinType* natural_join_type_; -}; - -class InnerJoinType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class NaturalJoinType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptInner* opt_inner_; - OptOuter* opt_outer_; -}; - -class OptInner: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptOuter: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OuterJoinType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptOuter* opt_outer_; -}; - -class SelectItemList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - SelectItem* select_item_; - SelectItemList* select_item_list_; -}; - -class SelectItem: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableWild* table_wild_; - OptAlias* opt_alias_; - ExprRoot* expr_root_; -}; - -class TableWild: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - TableName* table_name_; -}; - -class OptSelectOptions: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - SelectOptionList* select_option_list_; -}; - -class SelectOptionList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - SelectOption* select_option_; - SelectOptionList* select_option_list_; -}; - -class SelectOption: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class QueryExpressionParens: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - QueryExpressionParens* query_expression_parens_; - QueryExpression* query_expression_; -}; - -class OptUnionOption: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptOrderClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OrderClause* order_clause_; -}; - -class OrderClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OrderList* order_list_; -}; - -class OptLimitClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - LimitClause* limit_clause_; -}; - -class LimitClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - LimitOptions* limit_options_; -}; - -class LimitOptions: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Iconst* iconst_1_; - Iconst* iconst_2_; -}; - -class WithClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WithList* with_list_; -}; - -class WithList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - CommonTableExpr* common_table_expr_; - WithList* with_list_; -}; - -class CommonTableExpr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Subquery* subquery_; - OptColumnList* opt_column_list_; - TableName* table_name_; -}; - -class ExprRootList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ExprRoot* expr_root_; - ExprRootList* expr_root_list_; -}; - -class ExprRoot: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_; -}; - -class Expr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_1_; - Expr* expr_2_; - BoolPri* bool_pri_; -}; - -class BoolPri: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - BoolPri* bool_pri_; - Predicate* predicate_; - CompOp* comp_op_; - AllSubquery* all_subquery_; -}; - -class Predicate: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - InSubquery* in_subquery_; - BitExpr* bit_expr_1_; - BitExpr* bit_expr_2_; - Expr* expr_; - ExprList* expr_list_; - Predicate* predicate_; - SimpleExpr* simple_expr_; -}; - -class BitExpr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - BitExpr* bit_expr_1_; - BitExpr* bit_expr_2_; - SimpleExpr* simple_expr_; -}; - -class SimpleExpr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Columnref* columnref_; - Literal* literal_; - Iconst* iconst_; - Fconst* fconst_; - Sconst* sconst_; - SimpleExpr* simple_expr_; - Subquery* subquery_; - TypeCast* type_cast_; - CaseExpr* case_expr_; - Function* function_; - Expr* expr_; -}; - -class Function: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ControlFunction* control_function_; - MathFunction* math_function_; - StringFunction* string_function_; - AggregateFunction* aggregate_function_; - WindowFunction* window_function_; -}; - -class StringFunction: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_1_; - Expr* expr_2_; - Expr* expr_3_; - Expr* expr_4_; - Expr* expr_5_; - ExprList* expr_list_; -}; - -class MathFunction: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_1_; - Expr* expr_2_; - Expr* expr_3_; -}; - -class WindowFunction: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowingClause* windowing_clause_; - Iconst* iconst_; - OptNullTreatment* opt_null_treatment_; - OptLeadLagInfo* opt_lead_lag_info_; - Expr* expr_; - OptFromFirstLast* opt_from_first_last_; -}; - -class OptNullTreatment: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptFromFirstLast: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptLeadLagInfo: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - LeadLagInfo* lead_lag_info_; -}; - -class LeadLagInfo: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Iconst* iconst_; - Expr* expr_; -}; - -class AggregateFunction: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptWindowingClause* opt_windowing_clause_; - Expr* expr_; - OptDistinct* opt_distinct_; - ExprList* expr_list_; - OptGconcatSeparator* opt_gconcat_separator_; - OptOrderClause* opt_order_clause_; -}; - -class OptGconcatSeparator: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Sconst* sconst_; -}; - -class OptDistinct: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class OptWindowingClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowingClause* windowing_clause_; -}; - -class WindowingClause: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowNameOrSpec* window_name_or_spec_; -}; - -class WindowNameOrSpec: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WindowName* window_name_; - WindowSpec* window_spec_; -}; - -class ControlFunction: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_1_; - Expr* expr_2_; - Expr* expr_3_; -}; - -class CaseExpr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptElse* opt_else_; - WhenClasueList* when_clasue_list_; - OptExpr* opt_expr_; -}; - -class WhenClasueList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - WhenList* when_list_; - WhenClasueList* when_clasue_list_; -}; - -class WhenList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_1_; - Expr* expr_2_; -}; - -class OptExpr: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_; -}; - -class OptElse: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_; -}; - -class TypeCast: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - CastType* cast_type_; - Expr* expr_; -}; - -class CastType: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - OptFieldLength* opt_field_length_; - FloatOptions* float_options_; -}; - -class FloatOptions: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - FieldLength* field_length_; - Precision* precision_; -}; - -class Precision: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Iconst* iconst_1_; - Iconst* iconst_2_; -}; - -class OptFieldLength: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - FieldLength* field_length_; -}; - -class FieldLength: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Iconst* iconst_; -}; - -class Literal: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class Columnref: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - ColumnName* column_name_; - TableName* table_name_; -}; - -class CompOp: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - -}; - -class AllSubquery: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Subquery* subquery_; -}; - -class InSubquery: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Subquery* subquery_; -}; - -class ExprList: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Expr* expr_; - ExprList* expr_list_; -}; - -class Iconst: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - long int long_val_; -}; - -class Fconst: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - double float_val_; -}; - -class Sconst: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - string str_val_; -}; - -class Ident: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - string str_val_; -}; - -class Alias: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -class ColumnName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -class WindowName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -class TableName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -class ConstraintName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -class IndexName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -class ViewName: public Node { -public: - virtual IR* translate(); - virtual void deep_delete(); - - Ident* ident_; -}; - -#endif \ No newline at end of file diff --git a/include/connector.h b/include/connector.h deleted file mode 100755 index 7418dc4..0000000 --- a/include/connector.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __CONNECTOR_H__ -#define __CONNECTOR_H__ - -#include -#include -#include -#include -#include -#include -#include - -#include "libpq-fe.h" - -using namespace std; - -#define BUF_SIZE 1024 - -enum class SQLSTATUS { - ssNormal, - ssConnectFailed, - ssServerCrash, - ssSyntaxError, - ssSemanticError, - ssNoDatabase -}; - -class Connector { -public: - Connector(const char* host, const char* userName, const char* password, unsigned int port, const char* serverName); - - SQLSTATUS execute(const char* sql); - bool start_db(const char* file, char* const options[]); - bool close_db(); - -private: - string conninfo_; - string serverName_; - - void reset_database(PGconn* conn); - SQLSTATUS reset_db(); - pid_t get_pid_by_name(); -}; - -#endif \ No newline at end of file diff --git a/include/define.h b/include/define.h deleted file mode 100755 index 23d0fce..0000000 --- a/include/define.h +++ /dev/null @@ -1,797 +0,0 @@ -#ifndef __DEFINE_H__ -#define __DEFINE_H__ - -#define SWITCHSTART switch(case_idx_){ -#define SWITCHEND default: assert(0); } - -#define CASESTART(idx) case CASE##idx: { -#define CASEEND break; } - -#define TRANSLATESTART IR *res = nullptr; -#define TRANSLATEEND return res; - -#define SAFETRANSLATE(a) (assert(a != nullptr), a->translate()) -#define SAFEDELETE(a) if(a != nullptr) a->deep_delete() - -#define OP0() new IROperator(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty) -#define OP3(a,b,c) new IROperator(a,b,c) - -#define ALLTYPE(V) \ - V(kNone) \ - V(kParseToplevel) \ - V(kStmtmulti) \ - V(kStmt) \ - V(kDeleteStmt) \ - V(kDeleteStmtTmp1) \ - V(kDeleteStmtTmp2) \ - V(kDeleteStmtTmp3) \ - V(kDeleteStmtTmp4) \ - V(kDeleteStmtTmp5) \ - V(kDeleteStmtTmp6) \ - V(kDeleteStmtTmp7) \ - V(kDeleteStmtTmp8) \ - V(kOptDeleteOptions) \ - V(kDeleteOptions) \ - V(kDeleteOption) \ - V(kAlterTableStmt) \ - V(kAlterList) \ - V(kAlterListItem) \ - V(kAlterListItemTmp1) \ - V(kAlterListItemTmp2) \ - V(kOptPlace) \ - V(kDropIndexStmt) \ - V(kDropTableStmt) \ - V(kIfExists) \ - V(kTableList) \ - V(kDropViewStmt) \ - V(kUpdateStmt) \ - V(kUpdateStmtTmp1) \ - V(kUpdateStmtTmp2) \ - V(kUpdateStmtTmp3) \ - V(kUpdateStmtTmp4) \ - V(kUpdateStmtTmp5) \ - V(kUpdateStmtTmp6) \ - V(kOptSimpleLimit) \ - V(kOptWithClause) \ - V(kOptLowPriority) \ - V(kInsertStmt) \ - V(kInsertStmtTmp1) \ - V(kInsertStmtTmp2) \ - V(kInsertStmtTmp3) \ - V(kInsertStmtTmp4) \ - V(kInsertStmtTmp5) \ - V(kInsertStmtTmp6) \ - V(kInsertStmtTmp7) \ - V(kInsertStmtTmp8) \ - V(kInsertStmtTmp9) \ - V(kInsertStmtTmp10) \ - V(kInsertQueryExpression) \ - V(kInsertFromConstructor) \ - V(kValuesList) \ - V(kRowValue) \ - V(kOptValues) \ - V(kValues) \ - V(kExprOrDefault) \ - V(kOptValuesReference) \ - V(kOptInsertUpdateList) \ - V(kUpdateList) \ - V(kUpdateElem) \ - V(kInsertLockOption) \ - V(kOptIgnore) \ - V(kCreateIndexStmt) \ - V(kCreateIndexStmtTmp1) \ - V(kCreateIndexStmtTmp2) \ - V(kOptUnique) \ - V(kCreateViewStmt) \ - V(kCreateViewStmtTmp1) \ - V(kCreateViewStmtTmp2) \ - V(kCreateViewStmtTmp3) \ - V(kOptOrReplace) \ - V(kOptViewAlgorithm) \ - V(kCreateTableStmt) \ - V(kCreateTableStmtTmp1) \ - V(kCreateTableStmtTmp2) \ - V(kCreateTableStmtTmp3) \ - V(kCreateTableStmtTmp4) \ - V(kCreateTableStmtTmp5) \ - V(kOptTemporary) \ - V(kOptIfNotExists) \ - V(kOptDuplicateAsQe) \ - V(kDuplicateAsQe) \ - V(kDuplicate) \ - V(kTableElementList) \ - V(kTableElement) \ - V(kColumnDef) \ - V(kFieldDef) \ - V(kDataType) \ - V(kStringType) \ - V(kBoolType) \ - V(kNumberType) \ - V(kNumberTypeTmp1) \ - V(kNumberTypeTmp2) \ - V(kNumericType) \ - V(kRealType) \ - V(kOptPrecision) \ - V(kIntType) \ - V(kOptFieldOptions) \ - V(kFieldOptionList) \ - V(kFieldOption) \ - V(kOptColumnAttributeList) \ - V(kColumnAttributeList) \ - V(kColumnAttribute) \ - V(kDefaultAttribute) \ - V(kNotNull) \ - V(kVisibility) \ - V(kOptConstraintName) \ - V(kCheckConstraint) \ - V(kTableConstraintDef) \ - V(kTableConstraintDefTmp1) \ - V(kTableConstraintDefTmp2) \ - V(kTableConstraintDefTmp3) \ - V(kTableConstraintDefTmp4) \ - V(kReferences) \ - V(kReferencesTmp1) \ - V(kOptOnUpdateDelete) \ - V(kOnUpdateOption) \ - V(kKeyList) \ - V(kKeyListWithExpression) \ - V(kKeyPartWithExpression) \ - V(kKeyPart) \ - V(kKeyPartTmp1) \ - V(kConstraintKeyType) \ - V(kOptIndexName) \ - V(kSelectStmt) \ - V(kQueryExpression) \ - V(kQueryExpressionTmp1) \ - V(kQueryExpressionTmp2) \ - V(kQueryExpressionBody) \ - V(kQueryExpressionBodyTmp1) \ - V(kQueryPrimary) \ - V(kQuerySpecification) \ - V(kQuerySpecificationTmp1) \ - V(kQuerySpecificationTmp2) \ - V(kQuerySpecificationTmp3) \ - V(kQuerySpecificationTmp4) \ - V(kQuerySpecificationTmp5) \ - V(kOptWindowClause) \ - V(kWindowDefinitionList) \ - V(kWindowDefinition) \ - V(kWindowSpec) \ - V(kWindowSpecDetails) \ - V(kWindowSpecDetailsTmp1) \ - V(kWindowSpecDetailsTmp2) \ - V(kOptExistingWindowName) \ - V(kOptPartitionClause) \ - V(kOptWindowOrderByClause) \ - V(kOrderList) \ - V(kOrderExpr) \ - V(kOptOrderingDirection) \ - V(kOptWindowFrameClause) \ - V(kWindowFrameUnits) \ - V(kWindowFrameExtent) \ - V(kWindowFrameStart) \ - V(kWindowFrameBetween) \ - V(kWindowFrameBound) \ - V(kOptHavingClause) \ - V(kOptGroupClause) \ - V(kOlapOpt) \ - V(kOptWhereClause) \ - V(kWhereClause) \ - V(kOptFromClause) \ - V(kFromClause) \ - V(kTableReferenceList) \ - V(kTableReference) \ - V(kTableFactor) \ - V(kTableReferenceListParens) \ - V(kJoinedTableParens) \ - V(kDerivedTable) \ - V(kDerivedTableTmp1) \ - V(kOptColumnList) \ - V(kColumnList) \ - V(kSubquery) \ - V(kSingleTable) \ - V(kOptAlias) \ - V(kJoinedTable) \ - V(kJoinedTableTmp1) \ - V(kJoinedTableTmp2) \ - V(kJoinedTableTmp3) \ - V(kJoinedTableTmp4) \ - V(kJoinedTableTmp5) \ - V(kJoinedTableTmp6) \ - V(kJoinedTableTmp7) \ - V(kJoinedTableTmp8) \ - V(kInnerJoinType) \ - V(kNaturalJoinType) \ - V(kOptInner) \ - V(kOptOuter) \ - V(kOuterJoinType) \ - V(kSelectItemList) \ - V(kSelectItem) \ - V(kTableWild) \ - V(kOptSelectOptions) \ - V(kSelectOptionList) \ - V(kSelectOption) \ - V(kQueryExpressionParens) \ - V(kOptUnionOption) \ - V(kOptOrderClause) \ - V(kOrderClause) \ - V(kOptLimitClause) \ - V(kLimitClause) \ - V(kLimitOptions) \ - V(kWithClause) \ - V(kWithList) \ - V(kCommonTableExpr) \ - V(kCommonTableExprTmp1) \ - V(kExprRootList) \ - V(kExprRoot) \ - V(kExpr) \ - V(kBoolPri) \ - V(kBoolPriTmp1) \ - V(kBoolPriTmp2) \ - V(kPredicate) \ - V(kPredicateTmp1) \ - V(kPredicateTmp2) \ - V(kBitExpr) \ - V(kSimpleExpr) \ - V(kFunction) \ - V(kStringFunction) \ - V(kStringFunctionTmp1) \ - V(kStringFunctionTmp2) \ - V(kStringFunctionTmp3) \ - V(kMathFunction) \ - V(kMathFunctionTmp1) \ - V(kWindowFunction) \ - V(kWindowFunctionTmp1) \ - V(kWindowFunctionTmp2) \ - V(kWindowFunctionTmp3) \ - V(kWindowFunctionTmp4) \ - V(kOptNullTreatment) \ - V(kOptFromFirstLast) \ - V(kOptLeadLagInfo) \ - V(kLeadLagInfo) \ - V(kAggregateFunction) \ - V(kAggregateFunctionTmp1) \ - V(kAggregateFunctionTmp2) \ - V(kAggregateFunctionTmp3) \ - V(kAggregateFunctionTmp4) \ - V(kOptGconcatSeparator) \ - V(kOptDistinct) \ - V(kOptWindowingClause) \ - V(kWindowingClause) \ - V(kWindowNameOrSpec) \ - V(kControlFunction) \ - V(kControlFunctionTmp1) \ - V(kCaseExpr) \ - V(kCaseExprTmp1) \ - V(kWhenClasueList) \ - V(kWhenList) \ - V(kOptExpr) \ - V(kOptElse) \ - V(kTypeCast) \ - V(kCastType) \ - V(kFloatOptions) \ - V(kPrecision) \ - V(kOptFieldLength) \ - V(kFieldLength) \ - V(kLiteral) \ - V(kColumnref) \ - V(kCompOp) \ - V(kAllSubquery) \ - V(kInSubquery) \ - V(kExprList) \ - V(kIconst) \ - V(kFconst) \ - V(kSconst) \ - V(kIdent) \ - V(kAlias) \ - V(kColumnName) \ - V(kWindowName) \ - V(kTableName) \ - V(kConstraintName) \ - V(kIndexName) \ - V(kViewName) \ - -#define ALLCLASS(V) \ - V(ParseToplevel) \ - V(Stmtmulti) \ - V(Stmt) \ - V(DeleteStmt) \ - V(OptDeleteOptions) \ - V(DeleteOptions) \ - V(DeleteOption) \ - V(AlterTableStmt) \ - V(AlterList) \ - V(AlterListItem) \ - V(OptPlace) \ - V(DropIndexStmt) \ - V(DropTableStmt) \ - V(IfExists) \ - V(TableList) \ - V(DropViewStmt) \ - V(UpdateStmt) \ - V(OptSimpleLimit) \ - V(OptWithClause) \ - V(OptLowPriority) \ - V(InsertStmt) \ - V(InsertQueryExpression) \ - V(InsertFromConstructor) \ - V(ValuesList) \ - V(RowValue) \ - V(OptValues) \ - V(Values) \ - V(ExprOrDefault) \ - V(OptValuesReference) \ - V(OptInsertUpdateList) \ - V(UpdateList) \ - V(UpdateElem) \ - V(InsertLockOption) \ - V(OptIgnore) \ - V(CreateIndexStmt) \ - V(OptUnique) \ - V(CreateViewStmt) \ - V(OptOrReplace) \ - V(OptViewAlgorithm) \ - V(CreateTableStmt) \ - V(OptTemporary) \ - V(OptIfNotExists) \ - V(OptDuplicateAsQe) \ - V(DuplicateAsQe) \ - V(Duplicate) \ - V(TableElementList) \ - V(TableElement) \ - V(ColumnDef) \ - V(FieldDef) \ - V(DataType) \ - V(StringType) \ - V(BoolType) \ - V(NumberType) \ - V(NumericType) \ - V(RealType) \ - V(OptPrecision) \ - V(IntType) \ - V(OptFieldOptions) \ - V(FieldOptionList) \ - V(FieldOption) \ - V(OptColumnAttributeList) \ - V(ColumnAttributeList) \ - V(ColumnAttribute) \ - V(DefaultAttribute) \ - V(NotNull) \ - V(Visibility) \ - V(OptConstraintName) \ - V(CheckConstraint) \ - V(TableConstraintDef) \ - V(References) \ - V(OptOnUpdateDelete) \ - V(OnUpdateOption) \ - V(KeyList) \ - V(KeyListWithExpression) \ - V(KeyPartWithExpression) \ - V(KeyPart) \ - V(ConstraintKeyType) \ - V(OptIndexName) \ - V(SelectStmt) \ - V(QueryExpression) \ - V(QueryExpressionBody) \ - V(QueryPrimary) \ - V(QuerySpecification) \ - V(OptWindowClause) \ - V(WindowDefinitionList) \ - V(WindowDefinition) \ - V(WindowSpec) \ - V(WindowSpecDetails) \ - V(OptExistingWindowName) \ - V(OptPartitionClause) \ - V(OptWindowOrderByClause) \ - V(OrderList) \ - V(OrderExpr) \ - V(OptOrderingDirection) \ - V(OptWindowFrameClause) \ - V(WindowFrameUnits) \ - V(WindowFrameExtent) \ - V(WindowFrameStart) \ - V(WindowFrameBetween) \ - V(WindowFrameBound) \ - V(OptHavingClause) \ - V(OptGroupClause) \ - V(OlapOpt) \ - V(OptWhereClause) \ - V(WhereClause) \ - V(OptFromClause) \ - V(FromClause) \ - V(TableReferenceList) \ - V(TableReference) \ - V(TableFactor) \ - V(TableReferenceListParens) \ - V(JoinedTableParens) \ - V(DerivedTable) \ - V(OptColumnList) \ - V(ColumnList) \ - V(Subquery) \ - V(SingleTable) \ - V(OptAlias) \ - V(JoinedTable) \ - V(InnerJoinType) \ - V(NaturalJoinType) \ - V(OptInner) \ - V(OptOuter) \ - V(OuterJoinType) \ - V(SelectItemList) \ - V(SelectItem) \ - V(TableWild) \ - V(OptSelectOptions) \ - V(SelectOptionList) \ - V(SelectOption) \ - V(QueryExpressionParens) \ - V(OptUnionOption) \ - V(OptOrderClause) \ - V(OrderClause) \ - V(OptLimitClause) \ - V(LimitClause) \ - V(LimitOptions) \ - V(WithClause) \ - V(WithList) \ - V(CommonTableExpr) \ - V(ExprRootList) \ - V(ExprRoot) \ - V(Expr) \ - V(BoolPri) \ - V(Predicate) \ - V(BitExpr) \ - V(SimpleExpr) \ - V(Function) \ - V(StringFunction) \ - V(MathFunction) \ - V(WindowFunction) \ - V(OptNullTreatment) \ - V(OptFromFirstLast) \ - V(OptLeadLagInfo) \ - V(LeadLagInfo) \ - V(AggregateFunction) \ - V(OptGconcatSeparator) \ - V(OptDistinct) \ - V(OptWindowingClause) \ - V(WindowingClause) \ - V(WindowNameOrSpec) \ - V(ControlFunction) \ - V(CaseExpr) \ - V(WhenClasueList) \ - V(WhenList) \ - V(OptExpr) \ - V(OptElse) \ - V(TypeCast) \ - V(CastType) \ - V(FloatOptions) \ - V(Precision) \ - V(OptFieldLength) \ - V(FieldLength) \ - V(Literal) \ - V(Columnref) \ - V(CompOp) \ - V(AllSubquery) \ - V(InSubquery) \ - V(ExprList) \ - V(Iconst) \ - V(Fconst) \ - V(Sconst) \ - V(Ident) \ - V(Alias) \ - V(ColumnName) \ - V(WindowName) \ - V(TableName) \ - V(ConstraintName) \ - V(IndexName) \ - V(ViewName) \ - -#define ALLTERMINAL(V) \ - V(tOpSemi) \ - V(tFrom) \ - V(tDelete) \ - V(tEmpty) \ - V(tQuick) \ - V(tLowPriority) \ - V(tIgnore) \ - V(tAlterTable) \ - V(tOpComma) \ - V(tAddColumn) \ - V(tOpRp) \ - V(tAddColumnOpLp) \ - V(tAdd) \ - V(tChangeColumn) \ - V(tModifyColumn) \ - V(tDropColumn) \ - V(tDropForeignKey) \ - V(tDropPrimaryKey) \ - V(tDropIndex) \ - V(tDropCheck) \ - V(tDropConstraint) \ - V(tSetDefaultOpLp) \ - V(tAlterColumn) \ - V(tDropDefault) \ - V(tSet) \ - V(tAlterIndex) \ - V(tRenameTo) \ - V(tTo) \ - V(tRenameIndex) \ - V(tRenameColumn) \ - V(tAfter) \ - V(tFirst) \ - V(tOn) \ - V(tDropTable) \ - V(tIfExists) \ - V(tDropView) \ - V(tUpdate) \ - V(tLimit) \ - V(tInto) \ - V(tInsert) \ - V(tOpLp) \ - V(tValues) \ - V(tOpRpValues) \ - V(tDefault) \ - V(tAs) \ - V(tOnDuplicateKeyUpdate) \ - V(tOpEqual) \ - V(tDelayed) \ - V(tHighPriority) \ - V(tIndex) \ - V(tCreate) \ - V(tUnique) \ - V(tView) \ - V(tOrReplace) \ - V(tAlgorithmOpEqualUndefined) \ - V(tAlgorithmOpEqualMerge) \ - V(tAlgorithmOpEqualTemptable) \ - V(tTable) \ - V(tTemporary) \ - V(tIfNotExists) \ - V(tReplace) \ - V(tChar) \ - V(tBinary) \ - V(tVarchar) \ - V(tVarbinary) \ - V(tLongVarbinary) \ - V(tTinyblob) \ - V(tMediumblob) \ - V(tLongblob) \ - V(tBlob) \ - V(tTinytext) \ - V(tMediumtext) \ - V(tLongtext) \ - V(tText) \ - V(tBool) \ - V(tBoolean) \ - V(tFloat) \ - V(tDecimal) \ - V(tNumeric) \ - V(tFixed) \ - V(tReal) \ - V(tDouble) \ - V(tInt) \ - V(tTinyint) \ - V(tSmallint) \ - V(tMediumint) \ - V(tBigint) \ - V(tSigned) \ - V(tUnsigned) \ - V(tZerofill) \ - V(tDefaultOpLp) \ - V(tNotNull) \ - V(tVisible) \ - V(tInvisible) \ - V(tConstraint) \ - V(tCheckOpLp) \ - V(tForeignKey) \ - V(tReferences) \ - V(tOnUpdate) \ - V(tOnDelete) \ - V(tCascade) \ - V(tSetNull) \ - V(tNoAction) \ - V(tSetDefault) \ - V(tPrimaryKey) \ - V(tUnion) \ - V(tExcept) \ - V(tIntersect) \ - V(tSelect) \ - V(tWindow) \ - V(tPartitionBy) \ - V(tOrderBy) \ - V(tAsc) \ - V(tDesc) \ - V(tRows) \ - V(tRange) \ - V(tUnboundedPreceding) \ - V(tPreceding) \ - V(tCurrentRow) \ - V(tAnd) \ - V(tBetween) \ - V(tUnboundedFollowing) \ - V(tFollowing) \ - V(tHaving) \ - V(tGroupBy) \ - V(tWithRollup) \ - V(tWhere) \ - V(tLateral) \ - V(tUsingOpLp) \ - V(tJoin) \ - V(tInnerJoin) \ - V(tCrossJoin) \ - V(tStraightJoin) \ - V(tNatural) \ - V(tNaturalRight) \ - V(tNaturalLeft) \ - V(tInner) \ - V(tOuter) \ - V(tLeft) \ - V(tRight) \ - V(tOpMul) \ - V(tOpDotOpMul) \ - V(tSqlNoCache) \ - V(tDistinct) \ - V(tSqlSmallResult) \ - V(tSqlBigResult) \ - V(tSqlBufferResult) \ - V(tSqlCalcFoundRows) \ - V(tAll) \ - V(tWith) \ - V(tWithRecursive) \ - V(tOr) \ - V(tXor) \ - V(tNot) \ - V(tIsTrue) \ - V(tIsNotTrue) \ - V(tIsFalse) \ - V(tIsNotFalse) \ - V(tIsUnknown) \ - V(tIsNotUnknown) \ - V(tIsNull) \ - V(tIsNotNull) \ - V(tInOpLp) \ - V(tNotInOpLp) \ - V(tNotBetween) \ - V(tSoundsLike) \ - V(tLike) \ - V(tNotLike) \ - V(tRegexp) \ - V(tNotRegexp) \ - V(tOpOr) \ - V(tOpAnd) \ - V(tOpShl) \ - V(tOpShr) \ - V(tOpAdd) \ - V(tOpSub) \ - V(tOpDivide) \ - V(tOpMod) \ - V(tOpXor) \ - V(tOpNot) \ - V(tExists) \ - V(tAsciiOpLp) \ - V(tBinOpLp) \ - V(tBitLengthOpLp) \ - V(tCharLengthOpLp) \ - V(tLengthOpLp) \ - V(tLowerOpLp) \ - V(tLtrimOpLp) \ - V(tOctOpLp) \ - V(tOrdOpLp) \ - V(tQuoteOpLp) \ - V(tReverseOpLp) \ - V(tRtrimOpLp) \ - V(tSpaceOpLp) \ - V(tTrimOpLp) \ - V(tTrimOpLpLeadingFrom) \ - V(tTrimOpLpTrailingFrom) \ - V(tUnhexOpLp) \ - V(tUpperOpLp) \ - V(tFindInSetOpLp) \ - V(tInstrOpLp) \ - V(tLeftOpLp) \ - V(tLocateOpLp) \ - V(tRepeatOpLp) \ - V(tRightOpLp) \ - V(tSubstringOpLp) \ - V(tTrimOpLpLeading) \ - V(tTrimOpLpTrailing) \ - V(tExportSetOpLp) \ - V(tLpadOpLp) \ - V(tReplaceOpLp) \ - V(tRpadOpLp) \ - V(tSubstringIndexOpLp) \ - V(tInsertOpLp) \ - V(tCharOpLp) \ - V(tConcatOpLp) \ - V(tConcatWsOpLp) \ - V(tEltOpLp) \ - V(tFieldOpLp) \ - V(tMakeSetOpLp) \ - V(tPiOpLpOpRp) \ - V(tRandOpLpOpRp) \ - V(tAbsOpLp) \ - V(tAcosOpLp) \ - V(tAsinOpLp) \ - V(tAtanOpLp) \ - V(tCeilingOpLp) \ - V(tCosOpLp) \ - V(tCotOpLp) \ - V(tDegreesOpLp) \ - V(tExpOpLp) \ - V(tFloorOpLp) \ - V(tHexOpLp) \ - V(tLnOpLp) \ - V(tRadiansOpLp) \ - V(tRandOpLp) \ - V(tRoundOpLp) \ - V(tSignOpLp) \ - V(tSinOpLp) \ - V(tSqrtOpLp) \ - V(tTanOpLp) \ - V(tFormatOpLp) \ - V(tLogOpLp) \ - V(tModOpLp) \ - V(tPowOpLp) \ - V(tTruncateOpLp) \ - V(tConvOpLp) \ - V(tRowNumberOpLpOpRp) \ - V(tRankOpLpOpRp) \ - V(tDenseRankOpLpOpRp) \ - V(tCumeDistOpLpOpRp) \ - V(tPercentRankOpLpOpRp) \ - V(tNtileOpLp) \ - V(tLeadOpLp) \ - V(tLagOpLp) \ - V(tFirstValueOpLp) \ - V(tLastValueOpLp) \ - V(tNthValueOpLp) \ - V(tRespectNulls) \ - V(tIgnoreNulls) \ - V(tFromFirst) \ - V(tFromLast) \ - V(tAvgOpLp) \ - V(tBitAndOpLp) \ - V(tBitOrOpLp) \ - V(tBitXorOpLp) \ - V(tCountOpLpOpMulOpRp) \ - V(tCountOpLp) \ - V(tCountOpLpDistinct) \ - V(tMinOpLp) \ - V(tMaxOpLp) \ - V(tSumOpLp) \ - V(tStdOpLp) \ - V(tStddevSampOpLp) \ - V(tVarianceOpLp) \ - V(tVarSampOpLp) \ - V(tGroupConcatOpLp) \ - V(tSeparator) \ - V(tOver) \ - V(tIfOpLp) \ - V(tIfnullOpLp) \ - V(tNullifOpLp) \ - V(tEnd) \ - V(tCase) \ - V(tThen) \ - V(tWhen) \ - V(tElse) \ - V(tCastOpLp) \ - V(tConvertOpLp) \ - V(tNchar) \ - V(tNull) \ - V(tFalse) \ - V(tTrue) \ - V(tOpDot) \ - V(tOpGreatereq) \ - V(tOpGreaterthan) \ - V(tOpLesseq) \ - V(tOpLessthan) \ - V(tOpNotequal) \ - V(tAny) \ - V(tSome) \ - V(tIn) \ - V(tNotIn) \ - V(tIconst) \ - V(tFconst) \ - V(tSconst) \ - V(tIdent) \ - -#define IRNUMBER 273 - -#endif \ No newline at end of file diff --git a/include/instantiate.h b/include/instantiate.h deleted file mode 100755 index 9e9afa3..0000000 --- a/include/instantiate.h +++ /dev/null @@ -1,459 +0,0 @@ -#ifndef __INSTANTIATE_H__ -#define __INSTANTIATE_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ast.h" -#include "mutate.h" - -using namespace std; - -typedef uint8_t name_t; - -#define UNREFERENCE static_cast(-1) -#define COLUMNNAMEMAX 64 -#define RESERVEDCOLUMNNAME (COLUMNNAMEMAX - 1) - -#define LIMITMIN 1 -#define LIMITMAX 128 -#define OFFSETMIN 0 -#define OFFSETMAX 16 - -#define DEFAULTROWNUMBER -1 -#define DEFAULTCOLUMNNUMBER -1 - -#define MINSTRINGLENGTH 0 -#define MAXSTRINGLENGTH 64 - -#define CAPACITYBASE 80 -#define MAXCAPACITY 120 -#define CAPACITYGROWTHRATE 1.02 -#define TIMETHRESHOLD (3600 * 1000) - -#ifdef DEBUG -#define NT_check(ir, type) (assert(ir->type_ == type), ir) -#else -#define NT_check(ir, type) ir -#endif - -enum class IdentifierType { - iTable, - iColumn, - iWindow, - iIndex, - iConstraint, - iView -}; -enum class ColumnStatus { - csNormal, - csDuplication -}; -enum class ColumnType { - ctNull, ctInt, ctTinyInt, ctSmallInt, ctMediumInt, ctBigInt, - ctReal, ctDouble, ctFloat, ctDecimal, ctNumeric, ctFixed, - ctBool, ctBoolean, - ctChar, ctBinary, ctVarchar, ctVarbinary, ctLongVarbinary, - ctTinyBlob, ctMediumBlob, ctLongBlob, ctBlob, - ctTinyText, ctMediumText, ctLongText, ctText -}; -enum class TypeCompatibility { - tcNoCompatibility, - tcWeakCompatibility, - tcFullyCompatibility -}; -enum class IndexType { - itNormal, - itFunctional -}; -enum class ConstraintType { - ctNull, - ctUnique, - ctPrimaryKey, - ctCheck, - ctForeignKey -}; -enum class StmtLocation { - slNotSubquery, - slSubquery, - slCTE, - slRecursiveCTE, - slRecursivePart1, - slRecursivePart2, - slTableReference, - slWhereClause, - slGroupClause, - slTargetList, - slHavingClause, - slWindowClause, - slOrderClause -}; -enum class WindowStatus { - wsNoInherit, - wsInherit, - wsCantBeInherited, - wsWithOrder -}; -enum class ColumnBasicType { - ctString, - ctNumber, - ctBool -}; - -class Table; -class SelectStmtInfo; -class Instantiator; -class Constraint; - -class Column { -public: - Column(name_t name, ColumnType type); - Column(Column* column); - - bool notNull_ = false; - bool hasDefault_ = false; - bool isVisible_ = true; - name_t identifierName_; - ColumnStatus duplicated_ = ColumnStatus::csNormal; - ColumnType columnType_; - Table* parentTable_ = nullptr; - - static vector> compatibility_; - static map typeTranslation_; - static map typeToBasicType_; - - static void instantiate(); -}; - -class Index { -public: - Index(name_t name); - - name_t identifierName_; - Constraint* constraint_ = nullptr; - map columns_; -}; - -class Constraint { -public: - Constraint(name_t name, ConstraintType type); - - name_t identifierName_; - ConstraintType constraintType_; - Index* index_ = nullptr; - map columns_; - map> refToOtherColumns_; -}; - -class Table { -public: - Table(name_t name, IdentifierType identifierType, SelectStmtInfo* inSelectStmtInfo); - Table(Table* otherTable, SelectStmtInfo* inSelectStmtInfo); - ~Table(); - - bool isSubQuery_ = false; - bool isTemporary_ = false; - bool hasPrimaryKey_ = false; - name_t identifierName_; - IdentifierType identifierType_; - SelectStmtInfo* inSelectStmtInfo_ = nullptr; - - vector acceColumnNames_; - vector columns_; - - vector indexes_; - - vector constraints_; - map> refFromOtherColumns_; - - bool check_drop_table(); - bool exist_duplicated_column(); - void update_duplicationInfo(vector& duplicationInfo); - void update_duplicatedColumns(vector& duplicationInfo); - - bool column_drop_check(Column* column); - Column* get_column(); - Column* get_column(ColumnType type); - name_t get_acce_column_name(); - vector get_column_seq(); - void add_column_first(Column* column); - bool add_column(Column* column, Column* afterColumn = nullptr); - void move_column_first(Column* column); - bool move_column(Column* column, Column* afterColumn); - bool drop_column(Column* column); - - void column_rename(Column* column, name_t oldName, name_t newName); - - Index* get_index(); - vector get_index(Column* column); - bool add_index(Index* index); - bool drop_index(Index* index); - - Constraint* get_constraint(); - vector get_constraint(Column* column); - bool add_constraint(Constraint* constraint, Index* index = nullptr); - bool drop_constraint(Constraint* constraint); - bool set_references(Column* curTableColumn, Column* otherTableColumn); - bool remove_references(Column* curTableColumn, Column* otherTableColumn); - - bool remove_column_name(name_t name); - bool add_column_name(name_t name); - void drop_index(Column* column); - void drop_constraint(Column* column); - - bool index_drop_check(Index* index); - - bool constraint_drop_check(Constraint* constraint); -}; - -class SelectStmtInfo { -public: - SelectStmtInfo(StmtLocation location, int rowNumber, int columnNumber); - ~SelectStmtInfo(); - - bool hasAggregate = false; - - int columnNumber_; - int rowNumber_; - - name_t recursiveCteName_ = UNREFERENCE; - Table* recursiveCte_ = nullptr; - - StmtLocation location_; - - vector innerCteTables_; - vector outCteTables_; - - vector outReferences_; - - vector usedOutColumns_; - vector usedInnerColumns_; - - vector usedTables_; - vector acceColumns_; - - map windowStatusRecord_; - - bool is_duplicated_table(Table* table); - bool exist_duplicated_column(vector& v1, vector& v2); - bool has_column_limit(); - bool has_row_limit(); - - void add_used_table(Table* table); - void clear_local_info(); - void clear_cte(); - - void update_acceColumns(); - void update_acceColumns(vector& usedTables, vector& duplicationInfo); - - void add_usedInnerColumns(Column* column); - void add_usedOutColumns(Column* column); - void add_out_usedColumns(vector& usedColumns); - void add_all_usedColumns(vector& usedColumns); - -private: - vector duplicationInfo_ = vector(COLUMNNAMEMAX, 0); -}; - -class GlobalStatusManger { -public: - ~GlobalStatusManger(); - - stack selectInfoStack_; - - vector ignoreInnerUsedColumns_ = { StmtLocation::slWhereClause, StmtLocation::slTableReference, StmtLocation::slOrderClause }; - - void reset_status(); - - void push_selectInfo(StmtLocation location, int rowNumber, int columnNumber); - void pop_selectInfo(); - - SelectStmtInfo* get_cur_selectInfo(); - - int get_acce_table_number(); - Table* get_acce_table(int index); - vector get_acce_table(IdentifierType type); - - name_t get_new_table_name(); - name_t get_new_view_name(); - name_t get_new_window_name(); - name_t get_new_index_name(); - name_t get_new_constraint_name(); - - bool add_table(Table* table); - bool drop_table(Table* table); - bool drop_table(name_t name, IdentifierType type); - -private: - name_t totalTableName_ = 0; - name_t totalViewName_ = 0; - name_t totalWindowName_ = 0; - name_t totalIndexName_ = 0; - name_t totalConstraintName_ = 0; - - vector globalTables_; - - void pop_cur_selectInfo(); -}; - -class IRTrim { -public: - IRTrim(Instantiator* instantiator); - ~IRTrim(); - - void instantiate_simple_limit(); - void instantiate_simple_column_list(); - void instantiate_simple_alias(); - void instantiate_simple_expr_root(); - void instantiate_simple_expr_root_true(); - void instantiate_simple_expr_root_list(); - void instantiate_simple_simple_select_item_list(); - void instantiate_simple_window_spec(); - void instantiate_simple_index_name(); - void instantiate_simple_constraint_name(); - void instantiate_simple_key_part(); - void instantiate_simple_key_part_list(); - void instantiate_simple_table_element(); - void instantiate_simple_values(); - - IR* get_expr_root_columnref(Column* column); - void set_recursive_limit(IR* expr_root); - - IR* simple_limit_ = nullptr; - IR* simple_column_list_ = nullptr; - IR* simple_alias_ = nullptr; - IR* simple_expr_root_ = nullptr; - IR* simple_expr_root_true_ = nullptr; - IR* simple_expr_root_list_ = nullptr; - IR* simple_select_item_list_ = nullptr; - IR* simple_window_spec_ = nullptr; - IR* simple_index_name_ = nullptr; - IR* simple_constraint_name_ = nullptr; - IR* simple_key_part_ = nullptr; - IR* simple_key_part_list_ = nullptr; - IR* simple_table_element_ = nullptr; - IR* simple_values_ = nullptr; - - IR* expr_root_columnref_ = nullptr; - -private: - vector simpleIR_; - Instantiator* instantiator_; -}; - -class ExprInstantiator { -public: - ExprInstantiator(Instantiator* m): instantiator_(m){} - - vector usedColumnsBuffer_; - - void instantiate_expr_root(IR* expr_root, vector& acceColumns, StmtLocation location); - void instantiate_expr(IR* expr, vector& acceColumns, StmtLocation location); - void instantiate_simple_expr(IR* simple_expr, vector& acceColumns, StmtLocation location); - void instantiate_type_cast(IR* type_cast, vector& acceColumns, StmtLocation location); - void instantiate_function(IR* function, vector& acceColumns, StmtLocation location); - void instantiate_aggregate_function(IR* aggregate_function, vector& acceColumns, StmtLocation location); - void instantiate_window_function(IR* window_function, vector& acceColumns, StmtLocation location); - - long int get_random_integer(long int min = LONG_MIN, long int max = LONG_MAX); - double get_random_float(int min = INT_MIN, int max = INT_MAX); - string get_random_string(int minLength, int maxLength); - -private: - Instantiator* instantiator_; - vector ignoreSimpleExpr_ = { IRTYPE::kSimpleExpr, IRTYPE::kCaseExpr, IRTYPE::kExpr, IRTYPE::kLiteral }; -}; - -class Instantiator { -public: - Instantiator(); - ~Instantiator(); - - chrono::time_point startTime; - unsigned int get_duration_ms(); - - bool instantaite_sql(IR* root); - int calc_capacity(IR* root); - int calc_node(IR* root); - - IRTrim* IRTrim_; - GlobalStatusManger* globalStatusManger_; - ExprInstantiator* exprInstantiator_; - - void instantiate_parse_toplevel(IR* parse_toplevel); - - void instantiate_alter_table_stmt(IR* alter_table_stmt); - void instantiate_alter_list_item(IR* alter_list_item, Table* table); - - void instantiate_insert_stmt(IR* insert_stmt); - void instantiate_values_list(IR* values_list, int chosenColumnNumber); - void instantiate_values(IR* values, int chosenColumnNumber); - - void instantiate_update_stmt(IR* update_stmt); - int instantiate_update_list(IR* update_list, Table* table); - - void instantiate_delete_stmt(IR* delete_stmt); - - void instantiate_drop_table_or_view_stmt(IR* drop_table_stmt, IdentifierType type); - - void instantiate_drop_index_stmt(IR* drop_index_stmt); - - void instantiate_create_index_stmt(IR* create_index_stmt); - - void instantiate_create_view_stmt(IR* create_view_stmt); - - void instantiate_create_table_stmt(IR* create_table_stmt); - void instantiate_table_element_list(IR* table_element_list, Table* table); - pair> instantiate_column_def(IR* column_def, Table* table); - ColumnType instantiate_data_type(IR* data_type); - void instantiate_column_attribute(IR* column_attribute, Column* column, Table* table); - map instantiate_key_list_with_expression(IR* key_list_with_expression, Table* table, ConstraintType type); - bool instantiate_table_constraint_def_index(IR* table_constraint_def, Table* table); - bool instantiate_table_constraint_def_key(IR* table_constraint_def, Table* table); - bool instantiate_table_constraint_def_check(IR* table_constraint_def, Table* table); - bool instantiate_table_constraint_def_foreign_key(IR* table_constraint_def, Table* table); - - void instantiate_select_stmt(IR* select_stmt); - Table* instantiate_query_expression(IR* subquery, StmtLocation location, int rowNumber, int columnNumber); - Table* instantiate_query_expression(IR* query_expression); - Table* instantiate_query_primary(IR* query_primary); - Table* instanitate_union(IR* query_expression_body); - - void instantiate_with_clause(IR* with_clause); - void instantiate_order_clause(IR* order_clause); - void instantiate_limit_clause(IR* limit_clause); - - Table* instantiate_select_item_list(IR* select_item_list); - void instantiate_from_clause(IR* from_clause); - vector instantiate_table_reference(IR* table_reference); - Table* instantiate_single_table(IR* single_table); - Table* instantiate_derived_table(IR* derived_table); - vector instantiate_joined_table(IR* joined_table); - void instantiate_where_clause(IR* where_clause); - void instantiate_group_clause(IR* group_clause); - void instantiate_having_clause(IR* having_clause); - void instantiate_window_clause(IR* window_clause); - void instantiate_window_definition(IR* window_definition); - WindowStatus instantiate_window_spec(IR* window_spec); - - void instantiate_column_list(IR* column_list, vector& columns); - void instantiate_column_list(IR* column_list, vector& columns); - void instantiate_key_list(IR* key_list, vector& columns); - void instantiate_ident(IR* identifier_name, IdentifierType type, name_t name); - - bool check_foreign_key(Table* table, vector& curTableColumn, vector& otherTableColumn); -}; - -#endif diff --git a/include/mutate.h b/include/mutate.h deleted file mode 100755 index 800c8a4..0000000 --- a/include/mutate.h +++ /dev/null @@ -1,207 +0,0 @@ -#ifndef __MUTATOR_H__ -#define __MUTATOR_H__ - - -#include "ast.h" -#include "define.h" -#include "instantiate.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TOPNUMBER 10 - -#ifdef CLOSEMETHOD -#define IRTYPEUPDATETHRESHOLD UINT_MAX -#define IRINFOUPDATETHRESHOLD UINT_MAX -#else -#define IRTYPEUPDATETHRESHOLD 100 -#define IRINFOUPDATETHRESHOLD 100 -#endif - -#define REWARDINCREMENT 10 -#define REWARDNEWCOVERAGE 10 - -#define TIMETHRESHOLD (3600 * 1000) - -#ifdef BALANCE -#define MUTATENUMBER 2 -#endif - -using namespace std; - -#define ERRORINDEX USHRT_MAX - -enum class MutateOperator { - moReplace, - moInsert, - moDelete -}; - -double get_random_double(int min, int max); - -typedef struct { - unsigned char stmt_; - unsigned char inSubquery_; - unsigned short int clause_; - unsigned short int parentIRType_; - unsigned short int parentIRItem_; -} IRContextS; - -class IRInfomation { -public: - IRInfomation(int prefix, int left, int middle, int right, int suffix); - IRInfomation(IR* root); - - bool operator!=(IRInfomation* info); - - TERMINAL prefix_; - IRTYPE left_; - TERMINAL middle_; - IRTYPE right_; - TERMINAL suffix_; -}; - -class IRInfoManger { -public: - IRInfoManger(); - ~IRInfoManger(); - - IRTYPE curIRType_; - - vector IRInfoChosenCount_; - - void create_new_context(IRContextS* context); - - void update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward); - - void add_IRInfomation(IRInfomation* info); - IRInfomation* get_IRInfomation(unsigned short int index); - vector get_IRInfo_index(IRContextS* context, double heat); - - unsigned short int get_index_of_IRInfo(IR* root); - - string print_IRInformation_status(); - -private: - vector IRInfomation_; - unordered_map>> contextDependentCount_; -}; - -class OperatorManger { -public: - OperatorManger(); - ~OperatorManger(); - - IRTYPE curIRType_; - vector OpInfoChosenCount_; - vector OpInfoFailedCount_; - - void create_new_context(IRContextS* context); - vector get_OpInfo_index(IRContextS* context, double heat); - MutateOperator get_operator(unsigned short int index); - - void update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward); - - string print_OperatorInformation_status(); - -private: - vector OperatorInfomation_; - map>> contextDependentCount_; -}; - -class InputInfo { -public: - InputInfo(); - ~InputInfo(); - - IRTYPE MutateIRType_; - unsigned short int MutateIRInfoItem_; - unsigned short int MutateOperatorItem_; - - IRContextS MutateContext_; - IR* input_; -}; - -class Mutator { -public: - Mutator(); - - ~Mutator(); - - unsigned int failedMutate_ = 0; - unsigned int totalMutate_ = 0; - - IR* IR_parser(const char* sql); - - vector mutate_all(const char* sql); - - void update_status(InputInfo* input, unsigned int execStatus, bool isValid); - - bool init_IR_library(string filePath); - bool init_IR_config_info(string filePath); - - void print_information(string outputPath); - -private: - static vector stmtIRType_; - static vector clauseIRType_; - - chrono::time_point startTime; - - unsigned int seedCount_ = 0; - vector mutateNumber_; - - map IRInfo_; - map OpInfo_; - map> IRTypeCount_; - - set not_mutatable_types_; - set sql_hash_; - - map> IR_library_; - map> IR_library_hash_; - - void free_IR_library(); - void free_IR_config_info(); - - uint64_t hash(string& sql); - vector get_all_files_in_dir(const char* dir_name); - - ParseToplevel* parser(const char* sql); - - bool add_ir_to_library(IR* root); - bool add_ir_to_library_no_deepcopy(IR* root); - - IR* get_ir_from_library(IRTYPE type); - - void extract_struct(IR* root); - - vector mutate(IR* root, IRContextS context, double heat); - IR* get_new_tree(IR* oldIRRoot, IR* curIR, IR* newIR); - - unsigned int get_duration_ms(); - double get_cur_heat(); - unsigned int get_cur_reward(); - - void print_IRType_information(string outputPath); - void print_IRInfo_information(string outputPath); - void print_Mutate_number(string outputPath); - void print_OpInfo_information(string outputPath); - - vector original_mutate(IR* root, IRContextS context, double heat); - - IR* strategy_delete(IR* root); - IR* strategy_insert(IR* root); - IR* strategy_replace(IR* root); - - IR* check_sql(string& sql); -}; - -#endif -- Gitee From 3d1fe4a1bbb1745ca223f7d6e1efa4dd9a146708 Mon Sep 17 00:00:00 2001 From: PengJiaScu Date: Thu, 16 Nov 2023 07:59:08 +0000 Subject: [PATCH 5/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pars?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- parser/Makefile | 30 - parser/bison.y | 4451 --------------------------------------- parser/flex.l | 339 --- parser/parser_typedef.h | 51 - 4 files changed, 4871 deletions(-) delete mode 100755 parser/Makefile delete mode 100755 parser/bison.y delete mode 100755 parser/flex.l delete mode 100755 parser/parser_typedef.h diff --git a/parser/Makefile b/parser/Makefile deleted file mode 100755 index f2be1cd..0000000 --- a/parser/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# bison's version is too old on OSX, allow user to pass in custom path -BISON?=bison -FLEX?=flex - -#BISON_VERSION=$(shell $(BISON) --version | head -n 1 | grep -o '[0-9]\.[0-9]\+') -#BISON_VERSION_SUPPORTED=$(shell echo $(BISON_VERSION) \>= 3.0 | bc) -#ifneq ($(BISON_VERSION_SUPPORTED), 1) -#$(error Bison version $(BISON_VERSION) not supported. If you are using OS X, `bison` uses the system default instead of the brew version. Run BISON=/usr/local/opt/bison/bin/bison make) -#endif - -#FLEX_VERSION=$(shell $(FLEX) --version | head -n 1 | grep -o '[0-9]\.[0-9]\+') -#FLEX_VERSION_SUPPORTED=$(shell echo $(FLEX_VERSION) \>= 2.6 | bc) -#ifneq ($(FLEX_VERSION_SUPPORTED), 1) -#$(error Flex version $(FLEX_VERSION) not supported. If you are using OS X, `flex` uses the system default instead of the brew version. Run FLEX=/usr/local/opt/flex/bin/flex make) -#endif - -all: bison_parser.cpp flex_lexer.cpp - -bison_parser.cpp: bison.y - $(BISON) bison.y --output=bison_parser.cpp --defines=bison_parser.h --verbose -Wconflicts-rr - -flex_lexer.cpp: flex.l - $(FLEX) flex.l - -clean: - rm -f bison_parser.cpp flex_lexer.cpp bison_parser.h flex_lexer.h *.output - -# Tests if the parser builds correctly and doesn't contain conflicts. -test: - ! $(BISON) bison_parser.y -v --output=conflict_test.cpp 2>&1 | grep "conflict" >/tmp/2 diff --git a/parser/bison.y b/parser/bison.y deleted file mode 100755 index ec2eef9..0000000 --- a/parser/bison.y +++ /dev/null @@ -1,4451 +0,0 @@ -%{ -#include "bison_parser.h" -#include "flex_lexer.h" -#include -#include -int yyerror(YYLTYPE* llocp, ParseToplevel * result, yyscan_t scanner, const char *msg) { /*printf("%s\n", msg);*/ return 0; } -%} -%code requires { -#include "../include/ast.h" -#include "../include/instantiate.h" -#include "parser_typedef.h" -} -%define api.prefix {ff_} -%define parse.error verbose -%define api.pure full -%define api.token.prefix {SQL_} -%locations - -%initial-action { - @$.first_column = 0; - @$.last_column = 0; - @$.first_line = 0; - @$.last_line = 0; - @$.total_column = 0; - @$.string_length = 0; -}; - -%lex-param { yyscan_t scanner } -%parse-param { ParseToplevel* result } -%parse-param { yyscan_t scanner } - -%union FF_STYPE{ - long long_value; - char* charp_value; - double double_value; - - ParseToplevel* parse_toplevel_t; - Stmtmulti* stmtmulti_t; - Stmt* stmt_t; - DeleteStmt* delete_stmt_t; - OptDeleteOptions* opt_delete_options_t; - DeleteOptions* delete_options_t; - DeleteOption* delete_option_t; - AlterTableStmt* alter_table_stmt_t; - AlterList* alter_list_t; - AlterListItem* alter_list_item_t; - OptPlace* opt_place_t; - DropIndexStmt* drop_index_stmt_t; - DropTableStmt* drop_table_stmt_t; - IfExists* if_exists_t; - TableList* table_list_t; - DropViewStmt* drop_view_stmt_t; - UpdateStmt* update_stmt_t; - OptSimpleLimit* opt_simple_limit_t; - OptWithClause* opt_with_clause_t; - OptLowPriority* opt_low_priority_t; - InsertStmt* insert_stmt_t; - InsertQueryExpression* insert_query_expression_t; - InsertFromConstructor* insert_from_constructor_t; - ValuesList* values_list_t; - RowValue* row_value_t; - OptValues* opt_values_t; - Values* values_t; - ExprOrDefault* expr_or_default_t; - OptValuesReference* opt_values_reference_t; - OptInsertUpdateList* opt_insert_update_list_t; - UpdateList* update_list_t; - UpdateElem* update_elem_t; - InsertLockOption* insert_lock_option_t; - OptIgnore* opt_ignore_t; - CreateIndexStmt* create_index_stmt_t; - OptUnique* opt_unique_t; - CreateViewStmt* create_view_stmt_t; - OptOrReplace* opt_or_replace_t; - OptViewAlgorithm* opt_view_algorithm_t; - CreateTableStmt* create_table_stmt_t; - OptTemporary* opt_temporary_t; - OptIfNotExists* opt_if_not_exists_t; - OptDuplicateAsQe* opt_duplicate_as_qe_t; - DuplicateAsQe* duplicate_as_qe_t; - Duplicate* duplicate_t; - TableElementList* table_element_list_t; - TableElement* table_element_t; - ColumnDef* column_def_t; - FieldDef* field_def_t; - DataType* data_type_t; - StringType* string_type_t; - BoolType* bool_type_t; - NumberType* number_type_t; - NumericType* numeric_type_t; - RealType* real_type_t; - OptPrecision* opt_precision_t; - IntType* int_type_t; - OptFieldOptions* opt_field_options_t; - FieldOptionList* field_option_list_t; - FieldOption* field_option_t; - OptColumnAttributeList* opt_column_attribute_list_t; - ColumnAttributeList* column_attribute_list_t; - ColumnAttribute* column_attribute_t; - DefaultAttribute* default_attribute_t; - NotNull* not_null_t; - Visibility* visibility_t; - OptConstraintName* opt_constraint_name_t; - CheckConstraint* check_constraint_t; - TableConstraintDef* table_constraint_def_t; - References* references_t; - OptOnUpdateDelete* opt_on_update_delete_t; - OnUpdateOption* on_update_option_t; - KeyList* key_list_t; - KeyListWithExpression* key_list_with_expression_t; - KeyPartWithExpression* key_part_with_expression_t; - KeyPart* key_part_t; - ConstraintKeyType* constraint_key_type_t; - OptIndexName* opt_index_name_t; - SelectStmt* select_stmt_t; - QueryExpression* query_expression_t; - QueryExpressionBody* query_expression_body_t; - QueryPrimary* query_primary_t; - QuerySpecification* query_specification_t; - OptWindowClause* opt_window_clause_t; - WindowDefinitionList* window_definition_list_t; - WindowDefinition* window_definition_t; - WindowSpec* window_spec_t; - WindowSpecDetails* window_spec_details_t; - OptExistingWindowName* opt_existing_window_name_t; - OptPartitionClause* opt_partition_clause_t; - OptWindowOrderByClause* opt_window_order_by_clause_t; - OrderList* order_list_t; - OrderExpr* order_expr_t; - OptOrderingDirection* opt_ordering_direction_t; - OptWindowFrameClause* opt_window_frame_clause_t; - WindowFrameUnits* window_frame_units_t; - WindowFrameExtent* window_frame_extent_t; - WindowFrameStart* window_frame_start_t; - WindowFrameBetween* window_frame_between_t; - WindowFrameBound* window_frame_bound_t; - OptHavingClause* opt_having_clause_t; - OptGroupClause* opt_group_clause_t; - OlapOpt* olap_opt_t; - OptWhereClause* opt_where_clause_t; - WhereClause* where_clause_t; - OptFromClause* opt_from_clause_t; - FromClause* from_clause_t; - TableReferenceList* table_reference_list_t; - TableReference* table_reference_t; - TableFactor* table_factor_t; - TableReferenceListParens* table_reference_list_parens_t; - JoinedTableParens* joined_table_parens_t; - DerivedTable* derived_table_t; - OptColumnList* opt_column_list_t; - ColumnList* column_list_t; - Subquery* subquery_t; - SingleTable* single_table_t; - OptAlias* opt_alias_t; - JoinedTable* joined_table_t; - InnerJoinType* inner_join_type_t; - NaturalJoinType* natural_join_type_t; - OptInner* opt_inner_t; - OptOuter* opt_outer_t; - OuterJoinType* outer_join_type_t; - SelectItemList* select_item_list_t; - SelectItem* select_item_t; - TableWild* table_wild_t; - OptSelectOptions* opt_select_options_t; - SelectOptionList* select_option_list_t; - SelectOption* select_option_t; - QueryExpressionParens* query_expression_parens_t; - OptUnionOption* opt_union_option_t; - OptOrderClause* opt_order_clause_t; - OrderClause* order_clause_t; - OptLimitClause* opt_limit_clause_t; - LimitClause* limit_clause_t; - LimitOptions* limit_options_t; - WithClause* with_clause_t; - WithList* with_list_t; - CommonTableExpr* common_table_expr_t; - ExprRootList* expr_root_list_t; - ExprRoot* expr_root_t; - Expr* expr_t; - BoolPri* bool_pri_t; - Predicate* predicate_t; - BitExpr* bit_expr_t; - SimpleExpr* simple_expr_t; - Function* function_t; - StringFunction* string_function_t; - MathFunction* math_function_t; - WindowFunction* window_function_t; - OptNullTreatment* opt_null_treatment_t; - OptFromFirstLast* opt_from_first_last_t; - OptLeadLagInfo* opt_lead_lag_info_t; - LeadLagInfo* lead_lag_info_t; - AggregateFunction* aggregate_function_t; - OptGconcatSeparator* opt_gconcat_separator_t; - OptDistinct* opt_distinct_t; - OptWindowingClause* opt_windowing_clause_t; - WindowingClause* windowing_clause_t; - WindowNameOrSpec* window_name_or_spec_t; - ControlFunction* control_function_t; - CaseExpr* case_expr_t; - WhenClasueList* when_clasue_list_t; - WhenList* when_list_t; - OptExpr* opt_expr_t; - OptElse* opt_else_t; - TypeCast* type_cast_t; - CastType* cast_type_t; - FloatOptions* float_options_t; - Precision* precision_t; - OptFieldLength* opt_field_length_t; - FieldLength* field_length_t; - Literal* literal_t; - Columnref* columnref_t; - CompOp* comp_op_t; - AllSubquery* all_subquery_t; - InSubquery* in_subquery_t; - ExprList* expr_list_t; - Iconst* iconst_t; - Fconst* fconst_t; - Sconst* sconst_t; - Ident* ident_t; - Alias* alias_t; - ColumnName* column_name_t; - WindowName* window_name_t; - TableName* table_name_t; - ConstraintName* constraint_name_t; - IndexName* index_name_t; - ViewName* view_name_t; -} - -%token OP_SEMI FROM DELETE QUICK LOW_PRIORITY IGNORE ALTER TABLE OP_COMMA -%token ADD COLUMN OP_RP OP_LP CHANGE MODIFY DROP FOREIGN KEY PRIMARY -%token INDEX CHECK CONSTRAINT SET DEFAULT RENAME TO AFTER FIRST ON -%token IF EXISTS VIEW UPDATE LIMIT INTO INSERT VALUES AS DUPLICATE -%token OP_EQUAL DELAYED HIGH_PRIORITY CREATE UNIQUE OR REPLACE ALGORITHM UNDEFINED MERGE -%token TEMPTABLE TEMPORARY NOT CHAR BINARY VARCHAR VARBINARY LONG TINYBLOB MEDIUMBLOB -%token LONGBLOB BLOB TINYTEXT MEDIUMTEXT LONGTEXT TEXT BOOL BOOLEAN FLOAT DECIMAL -%token NUMERIC FIXED REAL DOUBLE INT TINYINT SMALLINT MEDIUMINT BIGINT SIGNED -%token UNSIGNED ZEROFILL NULL VISIBLE INVISIBLE REFERENCES CASCADE NO ACTION UNION -%token EXCEPT INTERSECT SELECT WINDOW PARTITION BY ORDER ASC DESC ROWS -%token RANGE UNBOUNDED PRECEDING CURRENT ROW AND BETWEEN FOLLOWING HAVING GROUP -%token WITH ROLLUP WHERE LATERAL USING JOIN INNER CROSS STRAIGHT_JOIN NATURAL -%token RIGHT LEFT OUTER OP_MUL OP_DOT SQL_NO_CACHE DISTINCT SQL_SMALL_RESULT SQL_BIG_RESULT SQL_BUFFER_RESULT -%token SQL_CALC_FOUND_ROWS ALL RECURSIVE XOR IS TRUE FALSE UNKNOWN IN SOUNDS -%token LIKE REGEXP OP_OR OP_AND OP_SHL OP_SHR OP_ADD OP_SUB OP_DIVIDE OP_MOD -%token OP_XOR OP_NOT ASCII BIN BIT_LENGTH CHAR_LENGTH LENGTH LOWER LTRIM OCT -%token ORD QUOTE REVERSE RTRIM SPACE TRIM LEADING TRAILING UNHEX UPPER -%token FIND_IN_SET INSTR LOCATE REPEAT SUBSTRING EXPORT_SET LPAD RPAD SUBSTRING_INDEX CONCAT -%token CONCAT_WS ELT FIELD MAKE_SET PI RAND ABS ACOS ASIN ATAN -%token CEILING COS COT DEGREES EXP FLOOR HEX LN RADIANS ROUND -%token SIGN SIN SQRT TAN FORMAT LOG MOD POW TRUNCATE CONV -%token ROW_NUMBER RANK DENSE_RANK CUME_DIST PERCENT_RANK NTILE LEAD LAG FIRST_VALUE LAST_VALUE -%token NTH_VALUE RESPECT NULLS LAST AVG BIT_AND BIT_OR BIT_XOR COUNT MIN -%token MAX SUM STD STDDEV_SAMP VARIANCE VAR_SAMP GROUP_CONCAT SEPARATOR OVER IFNULL -%token NULLIF END CASE THEN WHEN ELSE CAST CONVERT NCHAR OP_GREATEREQ -%token OP_GREATERTHAN OP_LESSEQ OP_LESSTHAN OP_NOTEQUAL ANY SOME - -%token IDENT -%token ICONST -%token FCONST -%token SCONST - -%type parse_toplevel -%type stmtmulti -%type stmt -%type delete_stmt -%type opt_delete_options -%type delete_options -%type delete_option -%type alter_table_stmt -%type alter_list -%type alter_list_item -%type opt_place -%type drop_index_stmt -%type drop_table_stmt -%type if_exists -%type table_list -%type drop_view_stmt -%type update_stmt -%type opt_simple_limit -%type opt_with_clause -%type opt_low_priority -%type insert_stmt -%type insert_query_expression -%type insert_from_constructor -%type values_list -%type row_value -%type opt_values -%type values -%type expr_or_default -%type opt_values_reference -%type opt_insert_update_list -%type update_list -%type update_elem -%type insert_lock_option -%type opt_ignore -%type create_index_stmt -%type opt_unique -%type create_view_stmt -%type opt_or_replace -%type opt_view_algorithm -%type create_table_stmt -%type opt_temporary -%type opt_if_not_exists -%type opt_duplicate_as_qe -%type duplicate_as_qe -%type duplicate -%type table_element_list -%type table_element -%type column_def -%type field_def -%type data_type -%type string_type -%type bool_type -%type number_type -%type numeric_type -%type real_type -%type opt_precision -%type int_type -%type opt_field_options -%type field_option_list -%type field_option -%type opt_column_attribute_list -%type column_attribute_list -%type column_attribute -%type default_attribute -%type not_null -%type visibility -%type opt_constraint_name -%type check_constraint -%type table_constraint_def -%type references -%type opt_on_update_delete -%type on_update_option -%type key_list -%type key_list_with_expression -%type key_part_with_expression -%type key_part -%type constraint_key_type -%type opt_index_name -%type select_stmt -%type query_expression -%type query_expression_body -%type query_primary -%type query_specification -%type opt_window_clause -%type window_definition_list -%type window_definition -%type window_spec -%type window_spec_details -%type opt_existing_window_name -%type opt_partition_clause -%type opt_window_order_by_clause -%type order_list -%type order_expr -%type opt_ordering_direction -%type opt_window_frame_clause -%type window_frame_units -%type window_frame_extent -%type window_frame_start -%type window_frame_between -%type window_frame_bound -%type opt_having_clause -%type opt_group_clause -%type olap_opt -%type opt_where_clause -%type where_clause -%type opt_from_clause -%type from_clause -%type table_reference_list -%type table_reference -%type table_factor -%type table_reference_list_parens -%type joined_table_parens -%type derived_table -%type opt_column_list -%type column_list -%type subquery -%type single_table -%type opt_alias -%type joined_table -%type inner_join_type -%type natural_join_type -%type opt_inner -%type opt_outer -%type outer_join_type -%type select_item_list -%type select_item -%type table_wild -%type opt_select_options -%type select_option_list -%type select_option -%type query_expression_parens -%type opt_union_option -%type opt_order_clause -%type order_clause -%type opt_limit_clause -%type limit_clause -%type limit_options -%type with_clause -%type with_list -%type common_table_expr -%type expr_root_list -%type expr_root -%type expr -%type bool_pri -%type predicate -%type bit_expr -%type simple_expr -%type function -%type string_function -%type math_function -%type window_function -%type opt_null_treatment -%type opt_from_first_last -%type opt_lead_lag_info -%type lead_lag_info -%type aggregate_function -%type opt_gconcat_separator -%type opt_distinct -%type opt_windowing_clause -%type windowing_clause -%type window_name_or_spec -%type control_function -%type case_expr -%type when_clasue_list -%type when_list -%type opt_expr -%type opt_else -%type type_cast -%type cast_type -%type float_options -%type precision -%type opt_field_length -%type field_length -%type literal -%type columnref -%type comp_op -%type all_subquery -%type in_subquery -%type expr_list -%type iconst -%type fconst -%type sconst -%type ident -%type alias -%type column_name -%type window_name -%type table_name -%type constraint_name -%type index_name -%type view_name - -%left UNION EXCEPT -%left INTERSECT -%left CONDITIONLESS_JOIN -%left JOIN INNER CROSS STRAIGHT_JOIN NATURAL LEFT RIGHT ON USING -%left OR -%left XOR -%left AND -%left BETWEEN CASE WHEN THEN ELSE -%left OP_GREATERTHAN OP_LESSTHAN OP_GREATEREQ OP_LESSEQ OP_NOTEQUAL OP_EQUAL IS LIKE REGEXP IN -%left OP_OR -%left OP_AND -%left OP_SHL OP_SHR -%left OP_ADD OP_SUB -%left OP_MUL OP_MOD OP_DIVIDE -%left OP_XOR -%left UMINUS OP_NOT -%right NOT -%left SUBQUERY_AS_EXPR -%left OP_RP OP_LP - -%destructor{ - free( ($$) ); -} - -%destructor{ - -} - -%destructor { if($$!=NULL)$$->deep_delete(); } <*> - -%start parse_toplevel - -%% - -parse_toplevel: - stmtmulti { - $$ = result; - $$->case_idx_ = CASE0; - - $$->stmtmulti_ = $1; - - $$ = NULL; - } - ; - -stmtmulti: - stmt OP_SEMI stmtmulti { - $$ = new Stmtmulti(); - $$->case_idx_ = CASE0; - - $$->stmt_ = $1; - $$->stmtmulti_ = $3; - } - |stmt OP_SEMI { - $$ = new Stmtmulti(); - $$->case_idx_ = CASE1; - - $$->stmt_ = $1; - } - ; - -stmt: - create_table_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE0; - - $$->create_table_stmt_ = $1; - } - |create_view_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE1; - - $$->create_view_stmt_ = $1; - } - |create_index_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE2; - - $$->create_index_stmt_ = $1; - } - |select_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE3; - - $$->select_stmt_ = $1; - } - |drop_index_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE4; - - $$->drop_index_stmt_ = $1; - } - |drop_table_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE5; - - $$->drop_table_stmt_ = $1; - } - |drop_view_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE6; - - $$->drop_view_stmt_ = $1; - } - |delete_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE7; - - $$->delete_stmt_ = $1; - } - |update_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE8; - - $$->update_stmt_ = $1; - } - |insert_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE9; - - $$->insert_stmt_ = $1; - } - |alter_table_stmt { - $$ = new Stmt(); - $$->case_idx_ = CASE10; - - $$->alter_table_stmt_ = $1; - } - ; - -delete_stmt: - opt_with_clause DELETE opt_delete_options FROM table_name opt_alias opt_where_clause opt_order_clause opt_simple_limit { - $$ = new DeleteStmt(); - $$->case_idx_ = CASE0; - - $$->opt_with_clause_ = $1; - $$->opt_delete_options_ = $3; - $$->table_name_ = $5; - $$->opt_alias_ = $6; - $$->opt_where_clause_ = $7; - $$->opt_order_clause_ = $8; - $$->opt_simple_limit_ = $9; - } - |opt_with_clause DELETE opt_delete_options table_list FROM table_reference_list opt_where_clause { - $$ = new DeleteStmt(); - $$->case_idx_ = CASE1; - - $$->opt_with_clause_ = $1; - $$->opt_delete_options_ = $3; - $$->table_list_ = $4; - $$->table_reference_list_ = $6; - $$->opt_where_clause_ = $7; - } - ; - -opt_delete_options: - { - $$ = new OptDeleteOptions(); - $$->case_idx_ = CASE0; - } - |delete_options { - $$ = new OptDeleteOptions(); - $$->case_idx_ = CASE1; - - $$->delete_options_ = $1; - } - ; - -delete_options: - delete_option { - $$ = new DeleteOptions(); - $$->case_idx_ = CASE0; - - $$->delete_option_ = $1; - } - |delete_option delete_options { - $$ = new DeleteOptions(); - $$->case_idx_ = CASE1; - - $$->delete_option_ = $1; - $$->delete_options_ = $2; - } - ; - -delete_option: - QUICK { - $$ = new DeleteOption(); - $$->case_idx_ = CASE0; - } - |LOW_PRIORITY { - $$ = new DeleteOption(); - $$->case_idx_ = CASE1; - } - |IGNORE { - $$ = new DeleteOption(); - $$->case_idx_ = CASE2; - } - ; - -alter_table_stmt: - ALTER TABLE table_name alter_list { - $$ = new AlterTableStmt(); - $$->case_idx_ = CASE0; - - $$->table_name_ = $3; - $$->alter_list_ = $4; - } - ; - -alter_list: - alter_list_item { - $$ = new AlterList(); - $$->case_idx_ = CASE0; - - $$->alter_list_item_ = $1; - } - |alter_list_item OP_COMMA alter_list { - $$ = new AlterList(); - $$->case_idx_ = CASE1; - - $$->alter_list_item_ = $1; - $$->alter_list_ = $3; - } - ; - -alter_list_item: - ADD COLUMN column_name field_def opt_place { - $$ = new AlterListItem(); - $$->case_idx_ = CASE0; - - $$->column_name_1_ = $3; - $$->field_def_ = $4; - $$->opt_place_ = $5; - } - |ADD COLUMN OP_LP table_element_list OP_RP { - $$ = new AlterListItem(); - $$->case_idx_ = CASE1; - - $$->table_element_list_ = $4; - } - |ADD table_constraint_def { - $$ = new AlterListItem(); - $$->case_idx_ = CASE2; - - $$->table_constraint_def_ = $2; - } - |CHANGE COLUMN column_name column_name field_def opt_place { - $$ = new AlterListItem(); - $$->case_idx_ = CASE3; - - $$->column_name_1_ = $3; - $$->column_name_2_ = $4; - $$->field_def_ = $5; - $$->opt_place_ = $6; - } - |MODIFY COLUMN column_name field_def opt_place { - $$ = new AlterListItem(); - $$->case_idx_ = CASE4; - - $$->column_name_1_ = $3; - $$->field_def_ = $4; - $$->opt_place_ = $5; - } - |DROP COLUMN column_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE5; - - $$->column_name_1_ = $3; - } - |DROP FOREIGN KEY constraint_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE6; - - $$->constraint_name_ = $4; - } - |DROP PRIMARY KEY { - $$ = new AlterListItem(); - $$->case_idx_ = CASE7; - } - |DROP INDEX index_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE8; - - $$->index_name_1_ = $3; - } - |DROP CHECK constraint_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE9; - - $$->constraint_name_ = $3; - } - |DROP CONSTRAINT constraint_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE10; - - $$->constraint_name_ = $3; - } - |ALTER COLUMN column_name SET DEFAULT OP_LP expr_root OP_RP { - $$ = new AlterListItem(); - $$->case_idx_ = CASE11; - - $$->column_name_1_ = $3; - $$->expr_root_ = $7; - } - |ALTER COLUMN column_name DROP DEFAULT { - $$ = new AlterListItem(); - $$->case_idx_ = CASE12; - - $$->column_name_1_ = $3; - } - |ALTER COLUMN column_name SET visibility { - $$ = new AlterListItem(); - $$->case_idx_ = CASE13; - - $$->column_name_1_ = $3; - $$->visibility_ = $5; - } - |ALTER INDEX index_name visibility { - $$ = new AlterListItem(); - $$->case_idx_ = CASE14; - - $$->index_name_1_ = $3; - $$->visibility_ = $4; - } - |RENAME TO table_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE15; - - $$->table_name_ = $3; - } - |RENAME INDEX index_name TO index_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE16; - - $$->index_name_1_ = $3; - $$->index_name_2_ = $5; - } - |RENAME COLUMN column_name TO column_name { - $$ = new AlterListItem(); - $$->case_idx_ = CASE17; - - $$->column_name_1_ = $3; - $$->column_name_2_ = $5; - } - ; - -opt_place: - { - $$ = new OptPlace(); - $$->case_idx_ = CASE0; - } - |AFTER column_name { - $$ = new OptPlace(); - $$->case_idx_ = CASE1; - - $$->column_name_ = $2; - } - |FIRST { - $$ = new OptPlace(); - $$->case_idx_ = CASE2; - } - ; - -drop_index_stmt: - DROP INDEX index_name ON table_name { - $$ = new DropIndexStmt(); - $$->case_idx_ = CASE0; - - $$->index_name_ = $3; - $$->table_name_ = $5; - } - ; - -drop_table_stmt: - DROP TABLE if_exists table_list { - $$ = new DropTableStmt(); - $$->case_idx_ = CASE0; - - $$->if_exists_ = $3; - $$->table_list_ = $4; - } - ; - -if_exists: - { - $$ = new IfExists(); - $$->case_idx_ = CASE0; - } - |IF EXISTS { - $$ = new IfExists(); - $$->case_idx_ = CASE1; - } - ; - -table_list: - table_name { - $$ = new TableList(); - $$->case_idx_ = CASE0; - - $$->table_name_ = $1; - } - |table_name OP_COMMA table_list { - $$ = new TableList(); - $$->case_idx_ = CASE1; - - $$->table_name_ = $1; - $$->table_list_ = $3; - } - ; - -drop_view_stmt: - DROP VIEW if_exists table_list { - $$ = new DropViewStmt(); - $$->case_idx_ = CASE0; - - $$->if_exists_ = $3; - $$->table_list_ = $4; - } - ; - -update_stmt: - opt_with_clause UPDATE opt_low_priority opt_ignore table_reference_list SET update_list opt_where_clause opt_order_clause opt_simple_limit { - $$ = new UpdateStmt(); - $$->case_idx_ = CASE0; - - $$->opt_with_clause_ = $1; - $$->opt_low_priority_ = $3; - $$->opt_ignore_ = $4; - $$->table_reference_list_ = $5; - $$->update_list_ = $7; - $$->opt_where_clause_ = $8; - $$->opt_order_clause_ = $9; - $$->opt_simple_limit_ = $10; - } - ; - -opt_simple_limit: - { - $$ = new OptSimpleLimit(); - $$->case_idx_ = CASE0; - } - |LIMIT iconst { - $$ = new OptSimpleLimit(); - $$->case_idx_ = CASE1; - - $$->iconst_ = $2; - } - ; - -opt_with_clause: - { - $$ = new OptWithClause(); - $$->case_idx_ = CASE0; - } - |with_clause { - $$ = new OptWithClause(); - $$->case_idx_ = CASE1; - - $$->with_clause_ = $1; - } - ; - -opt_low_priority: - { - $$ = new OptLowPriority(); - $$->case_idx_ = CASE0; - } - |LOW_PRIORITY { - $$ = new OptLowPriority(); - $$->case_idx_ = CASE1; - } - ; - -insert_stmt: - INSERT insert_lock_option opt_ignore INTO table_name insert_from_constructor opt_values_reference opt_insert_update_list { - $$ = new InsertStmt(); - $$->case_idx_ = CASE0; - - $$->insert_lock_option_ = $2; - $$->opt_ignore_ = $3; - $$->table_name_ = $5; - $$->insert_from_constructor_ = $6; - $$->opt_values_reference_ = $7; - $$->opt_insert_update_list_ = $8; - } - |INSERT insert_lock_option opt_ignore INTO table_name SET update_list opt_values_reference opt_insert_update_list { - $$ = new InsertStmt(); - $$->case_idx_ = CASE1; - - $$->insert_lock_option_ = $2; - $$->opt_ignore_ = $3; - $$->table_name_ = $5; - $$->update_list_ = $7; - $$->opt_values_reference_ = $8; - $$->opt_insert_update_list_ = $9; - } - |INSERT insert_lock_option opt_ignore INTO table_name insert_query_expression opt_insert_update_list { - $$ = new InsertStmt(); - $$->case_idx_ = CASE2; - - $$->insert_lock_option_ = $2; - $$->opt_ignore_ = $3; - $$->table_name_ = $5; - $$->insert_query_expression_ = $6; - $$->opt_insert_update_list_ = $7; - } - ; - -insert_query_expression: - query_expression { - $$ = new InsertQueryExpression(); - $$->case_idx_ = CASE0; - - $$->query_expression_ = $1; - } - |OP_LP column_list OP_RP query_expression { - $$ = new InsertQueryExpression(); - $$->case_idx_ = CASE1; - - $$->column_list_ = $2; - $$->query_expression_ = $4; - } - ; - -insert_from_constructor: - VALUES values_list { - $$ = new InsertFromConstructor(); - $$->case_idx_ = CASE0; - - $$->values_list_ = $2; - } - |OP_LP column_list OP_RP VALUES values_list { - $$ = new InsertFromConstructor(); - $$->case_idx_ = CASE1; - - $$->column_list_ = $2; - $$->values_list_ = $5; - } - ; - -values_list: - row_value { - $$ = new ValuesList(); - $$->case_idx_ = CASE0; - - $$->row_value_ = $1; - } - |row_value OP_COMMA values_list { - $$ = new ValuesList(); - $$->case_idx_ = CASE1; - - $$->row_value_ = $1; - $$->values_list_ = $3; - } - ; - -row_value: - OP_LP opt_values OP_RP { - $$ = new RowValue(); - $$->case_idx_ = CASE0; - - $$->opt_values_ = $2; - } - ; - -opt_values: - { - $$ = new OptValues(); - $$->case_idx_ = CASE0; - } - |values { - $$ = new OptValues(); - $$->case_idx_ = CASE1; - - $$->values_ = $1; - } - ; - -values: - expr_or_default { - $$ = new Values(); - $$->case_idx_ = CASE0; - - $$->expr_or_default_ = $1; - } - |expr_or_default OP_COMMA values { - $$ = new Values(); - $$->case_idx_ = CASE1; - - $$->expr_or_default_ = $1; - $$->values_ = $3; - } - ; - -expr_or_default: - expr_root { - $$ = new ExprOrDefault(); - $$->case_idx_ = CASE0; - - $$->expr_root_ = $1; - } - |DEFAULT { - $$ = new ExprOrDefault(); - $$->case_idx_ = CASE1; - } - ; - -opt_values_reference: - { - $$ = new OptValuesReference(); - $$->case_idx_ = CASE0; - } - |AS table_name opt_column_list { - $$ = new OptValuesReference(); - $$->case_idx_ = CASE1; - - $$->table_name_ = $2; - $$->opt_column_list_ = $3; - } - ; - -opt_insert_update_list: - { - $$ = new OptInsertUpdateList(); - $$->case_idx_ = CASE0; - } - |ON DUPLICATE KEY UPDATE update_list { - $$ = new OptInsertUpdateList(); - $$->case_idx_ = CASE1; - - $$->update_list_ = $5; - } - ; - -update_list: - update_elem { - $$ = new UpdateList(); - $$->case_idx_ = CASE0; - - $$->update_elem_ = $1; - } - |update_elem OP_COMMA update_list { - $$ = new UpdateList(); - $$->case_idx_ = CASE1; - - $$->update_elem_ = $1; - $$->update_list_ = $3; - } - ; - -update_elem: - columnref OP_EQUAL expr_or_default { - $$ = new UpdateElem(); - $$->case_idx_ = CASE0; - - $$->columnref_ = $1; - $$->expr_or_default_ = $3; - } - ; - -insert_lock_option: - { - $$ = new InsertLockOption(); - $$->case_idx_ = CASE0; - } - |LOW_PRIORITY { - $$ = new InsertLockOption(); - $$->case_idx_ = CASE1; - } - |DELAYED { - $$ = new InsertLockOption(); - $$->case_idx_ = CASE2; - } - |HIGH_PRIORITY { - $$ = new InsertLockOption(); - $$->case_idx_ = CASE3; - } - ; - -opt_ignore: - { - $$ = new OptIgnore(); - $$->case_idx_ = CASE0; - } - |IGNORE { - $$ = new OptIgnore(); - $$->case_idx_ = CASE1; - } - ; - -create_index_stmt: - CREATE opt_unique INDEX index_name ON table_name OP_LP key_list_with_expression OP_RP { - $$ = new CreateIndexStmt(); - $$->case_idx_ = CASE0; - - $$->opt_unique_ = $2; - $$->index_name_ = $4; - $$->table_name_ = $6; - $$->key_list_with_expression_ = $8; - } - ; - -opt_unique: - { - $$ = new OptUnique(); - $$->case_idx_ = CASE0; - } - |UNIQUE { - $$ = new OptUnique(); - $$->case_idx_ = CASE1; - } - ; - -create_view_stmt: - CREATE opt_or_replace opt_view_algorithm VIEW view_name opt_column_list AS query_expression { - $$ = new CreateViewStmt(); - $$->case_idx_ = CASE0; - - $$->opt_or_replace_ = $2; - $$->opt_view_algorithm_ = $3; - $$->view_name_ = $5; - $$->opt_column_list_ = $6; - $$->query_expression_ = $8; - } - ; - -opt_or_replace: - { - $$ = new OptOrReplace(); - $$->case_idx_ = CASE0; - } - |OR REPLACE { - $$ = new OptOrReplace(); - $$->case_idx_ = CASE1; - } - ; - -opt_view_algorithm: - { - $$ = new OptViewAlgorithm(); - $$->case_idx_ = CASE0; - } - |ALGORITHM OP_EQUAL UNDEFINED { - $$ = new OptViewAlgorithm(); - $$->case_idx_ = CASE1; - } - |ALGORITHM OP_EQUAL MERGE { - $$ = new OptViewAlgorithm(); - $$->case_idx_ = CASE2; - } - |ALGORITHM OP_EQUAL TEMPTABLE { - $$ = new OptViewAlgorithm(); - $$->case_idx_ = CASE3; - } - ; - -create_table_stmt: - CREATE opt_temporary TABLE opt_if_not_exists table_name OP_LP table_element_list OP_RP opt_duplicate_as_qe { - $$ = new CreateTableStmt(); - $$->case_idx_ = CASE0; - - $$->opt_temporary_ = $2; - $$->opt_if_not_exists_ = $4; - $$->table_name_ = $5; - $$->table_element_list_ = $7; - $$->opt_duplicate_as_qe_ = $9; - } - |CREATE opt_temporary TABLE opt_if_not_exists table_name duplicate_as_qe { - $$ = new CreateTableStmt(); - $$->case_idx_ = CASE1; - - $$->opt_temporary_ = $2; - $$->opt_if_not_exists_ = $4; - $$->table_name_ = $5; - $$->duplicate_as_qe_ = $6; - } - ; - -opt_temporary: - { - $$ = new OptTemporary(); - $$->case_idx_ = CASE0; - } - |TEMPORARY { - $$ = new OptTemporary(); - $$->case_idx_ = CASE1; - } - ; - -opt_if_not_exists: - { - $$ = new OptIfNotExists(); - $$->case_idx_ = CASE0; - } - |IF NOT EXISTS { - $$ = new OptIfNotExists(); - $$->case_idx_ = CASE1; - } - ; - -opt_duplicate_as_qe: - { - $$ = new OptDuplicateAsQe(); - $$->case_idx_ = CASE0; - } - |duplicate_as_qe { - $$ = new OptDuplicateAsQe(); - $$->case_idx_ = CASE1; - - $$->duplicate_as_qe_ = $1; - } - ; - -duplicate_as_qe: - duplicate AS query_expression { - $$ = new DuplicateAsQe(); - $$->case_idx_ = CASE0; - - $$->duplicate_ = $1; - $$->query_expression_ = $3; - } - |AS query_expression { - $$ = new DuplicateAsQe(); - $$->case_idx_ = CASE1; - - $$->query_expression_ = $2; - } - ; - -duplicate: - REPLACE { - $$ = new Duplicate(); - $$->case_idx_ = CASE0; - } - |IGNORE { - $$ = new Duplicate(); - $$->case_idx_ = CASE1; - } - ; - -table_element_list: - table_element { - $$ = new TableElementList(); - $$->case_idx_ = CASE0; - - $$->table_element_ = $1; - } - |table_element OP_COMMA table_element_list { - $$ = new TableElementList(); - $$->case_idx_ = CASE1; - - $$->table_element_ = $1; - $$->table_element_list_ = $3; - } - ; - -table_element: - column_def { - $$ = new TableElement(); - $$->case_idx_ = CASE0; - - $$->column_def_ = $1; - } - |table_constraint_def { - $$ = new TableElement(); - $$->case_idx_ = CASE1; - - $$->table_constraint_def_ = $1; - } - ; - -column_def: - column_name field_def { - $$ = new ColumnDef(); - $$->case_idx_ = CASE0; - - $$->column_name_ = $1; - $$->field_def_ = $2; - } - ; - -field_def: - data_type opt_column_attribute_list { - $$ = new FieldDef(); - $$->case_idx_ = CASE0; - - $$->data_type_ = $1; - $$->opt_column_attribute_list_ = $2; - } - ; - -data_type: - number_type { - $$ = new DataType(); - $$->case_idx_ = CASE0; - - $$->number_type_ = $1; - } - |bool_type { - $$ = new DataType(); - $$->case_idx_ = CASE1; - - $$->bool_type_ = $1; - } - |string_type { - $$ = new DataType(); - $$->case_idx_ = CASE2; - - $$->string_type_ = $1; - } - ; - -string_type: - CHAR opt_field_length { - $$ = new StringType(); - $$->case_idx_ = CASE0; - - $$->opt_field_length_ = $2; - } - |BINARY opt_field_length { - $$ = new StringType(); - $$->case_idx_ = CASE1; - - $$->opt_field_length_ = $2; - } - |VARCHAR field_length { - $$ = new StringType(); - $$->case_idx_ = CASE2; - - $$->field_length_ = $2; - } - |VARBINARY field_length { - $$ = new StringType(); - $$->case_idx_ = CASE3; - - $$->field_length_ = $2; - } - |LONG VARBINARY { - $$ = new StringType(); - $$->case_idx_ = CASE4; - } - |TINYBLOB { - $$ = new StringType(); - $$->case_idx_ = CASE5; - } - |MEDIUMBLOB { - $$ = new StringType(); - $$->case_idx_ = CASE6; - } - |LONGBLOB { - $$ = new StringType(); - $$->case_idx_ = CASE7; - } - |BLOB opt_field_length { - $$ = new StringType(); - $$->case_idx_ = CASE8; - - $$->opt_field_length_ = $2; - } - |TINYTEXT { - $$ = new StringType(); - $$->case_idx_ = CASE9; - } - |MEDIUMTEXT { - $$ = new StringType(); - $$->case_idx_ = CASE10; - } - |LONGTEXT { - $$ = new StringType(); - $$->case_idx_ = CASE11; - } - |TEXT { - $$ = new StringType(); - $$->case_idx_ = CASE12; - } - ; - -bool_type: - BOOL { - $$ = new BoolType(); - $$->case_idx_ = CASE0; - } - |BOOLEAN { - $$ = new BoolType(); - $$->case_idx_ = CASE1; - } - ; - -number_type: - int_type opt_field_options { - $$ = new NumberType(); - $$->case_idx_ = CASE0; - - $$->int_type_ = $1; - $$->opt_field_options_ = $2; - } - |real_type opt_precision opt_field_options { - $$ = new NumberType(); - $$->case_idx_ = CASE1; - - $$->real_type_ = $1; - $$->opt_precision_ = $2; - $$->opt_field_options_ = $3; - } - |numeric_type float_options opt_field_options { - $$ = new NumberType(); - $$->case_idx_ = CASE2; - - $$->numeric_type_ = $1; - $$->float_options_ = $2; - $$->opt_field_options_ = $3; - } - ; - -numeric_type: - FLOAT { - $$ = new NumericType(); - $$->case_idx_ = CASE0; - } - |DECIMAL { - $$ = new NumericType(); - $$->case_idx_ = CASE1; - } - |NUMERIC { - $$ = new NumericType(); - $$->case_idx_ = CASE2; - } - |FIXED { - $$ = new NumericType(); - $$->case_idx_ = CASE3; - } - ; - -real_type: - REAL { - $$ = new RealType(); - $$->case_idx_ = CASE0; - } - |DOUBLE { - $$ = new RealType(); - $$->case_idx_ = CASE1; - } - ; - -opt_precision: - { - $$ = new OptPrecision(); - $$->case_idx_ = CASE0; - } - |precision { - $$ = new OptPrecision(); - $$->case_idx_ = CASE1; - - $$->precision_ = $1; - } - ; - -int_type: - INT { - $$ = new IntType(); - $$->case_idx_ = CASE0; - } - |TINYINT { - $$ = new IntType(); - $$->case_idx_ = CASE1; - } - |SMALLINT { - $$ = new IntType(); - $$->case_idx_ = CASE2; - } - |MEDIUMINT { - $$ = new IntType(); - $$->case_idx_ = CASE3; - } - |BIGINT { - $$ = new IntType(); - $$->case_idx_ = CASE4; - } - ; - -opt_field_options: - { - $$ = new OptFieldOptions(); - $$->case_idx_ = CASE0; - } - |field_option_list { - $$ = new OptFieldOptions(); - $$->case_idx_ = CASE1; - - $$->field_option_list_ = $1; - } - ; - -field_option_list: - field_option { - $$ = new FieldOptionList(); - $$->case_idx_ = CASE0; - - $$->field_option_ = $1; - } - |field_option field_option_list { - $$ = new FieldOptionList(); - $$->case_idx_ = CASE1; - - $$->field_option_ = $1; - $$->field_option_list_ = $2; - } - ; - -field_option: - SIGNED { - $$ = new FieldOption(); - $$->case_idx_ = CASE0; - } - |UNSIGNED { - $$ = new FieldOption(); - $$->case_idx_ = CASE1; - } - |ZEROFILL { - $$ = new FieldOption(); - $$->case_idx_ = CASE2; - } - ; - -opt_column_attribute_list: - { - $$ = new OptColumnAttributeList(); - $$->case_idx_ = CASE0; - } - |column_attribute_list { - $$ = new OptColumnAttributeList(); - $$->case_idx_ = CASE1; - - $$->column_attribute_list_ = $1; - } - ; - -column_attribute_list: - column_attribute { - $$ = new ColumnAttributeList(); - $$->case_idx_ = CASE0; - - $$->column_attribute_ = $1; - } - |column_attribute column_attribute_list { - $$ = new ColumnAttributeList(); - $$->case_idx_ = CASE1; - - $$->column_attribute_ = $1; - $$->column_attribute_list_ = $2; - } - ; - -column_attribute: - not_null { - $$ = new ColumnAttribute(); - $$->case_idx_ = CASE0; - - $$->not_null_ = $1; - } - |default_attribute { - $$ = new ColumnAttribute(); - $$->case_idx_ = CASE1; - - $$->default_attribute_ = $1; - } - |visibility { - $$ = new ColumnAttribute(); - $$->case_idx_ = CASE2; - - $$->visibility_ = $1; - } - ; - -default_attribute: - DEFAULT OP_LP expr_root OP_RP { - $$ = new DefaultAttribute(); - $$->case_idx_ = CASE0; - - $$->expr_root_ = $3; - } - ; - -not_null: - NOT NULL { - $$ = new NotNull(); - $$->case_idx_ = CASE0; - } - ; - -visibility: - VISIBLE { - $$ = new Visibility(); - $$->case_idx_ = CASE0; - } - |INVISIBLE { - $$ = new Visibility(); - $$->case_idx_ = CASE1; - } - ; - -opt_constraint_name: - { - $$ = new OptConstraintName(); - $$->case_idx_ = CASE0; - } - |CONSTRAINT constraint_name { - $$ = new OptConstraintName(); - $$->case_idx_ = CASE1; - - $$->constraint_name_ = $2; - } - ; - -check_constraint: - CHECK OP_LP expr_root OP_RP { - $$ = new CheckConstraint(); - $$->case_idx_ = CASE0; - - $$->expr_root_ = $3; - } - ; - -table_constraint_def: - INDEX opt_index_name OP_LP key_list_with_expression OP_RP { - $$ = new TableConstraintDef(); - $$->case_idx_ = CASE0; - - $$->opt_index_name_ = $2; - $$->key_list_with_expression_ = $4; - } - |opt_constraint_name constraint_key_type opt_index_name OP_LP key_list_with_expression OP_RP { - $$ = new TableConstraintDef(); - $$->case_idx_ = CASE1; - - $$->opt_constraint_name_ = $1; - $$->constraint_key_type_ = $2; - $$->opt_index_name_ = $3; - $$->key_list_with_expression_ = $5; - } - |opt_constraint_name check_constraint { - $$ = new TableConstraintDef(); - $$->case_idx_ = CASE2; - - $$->opt_constraint_name_ = $1; - $$->check_constraint_ = $2; - } - |opt_constraint_name FOREIGN KEY opt_index_name OP_LP key_list OP_RP references { - $$ = new TableConstraintDef(); - $$->case_idx_ = CASE3; - - $$->opt_constraint_name_ = $1; - $$->opt_index_name_ = $4; - $$->key_list_ = $6; - $$->references_ = $8; - } - ; - -references: - REFERENCES table_name OP_LP column_list OP_RP opt_on_update_delete { - $$ = new References(); - $$->case_idx_ = CASE0; - - $$->table_name_ = $2; - $$->column_list_ = $4; - $$->opt_on_update_delete_ = $6; - } - ; - -opt_on_update_delete: - { - $$ = new OptOnUpdateDelete(); - $$->case_idx_ = CASE0; - } - |ON UPDATE on_update_option { - $$ = new OptOnUpdateDelete(); - $$->case_idx_ = CASE1; - - $$->on_update_option_1_ = $3; - } - |ON DELETE on_update_option { - $$ = new OptOnUpdateDelete(); - $$->case_idx_ = CASE2; - - $$->on_update_option_1_ = $3; - } - |ON UPDATE on_update_option ON DELETE on_update_option { - $$ = new OptOnUpdateDelete(); - $$->case_idx_ = CASE3; - - $$->on_update_option_1_ = $3; - $$->on_update_option_2_ = $6; - } - |ON DELETE on_update_option ON UPDATE on_update_option { - $$ = new OptOnUpdateDelete(); - $$->case_idx_ = CASE4; - - $$->on_update_option_1_ = $3; - $$->on_update_option_2_ = $6; - } - ; - -on_update_option: - CASCADE { - $$ = new OnUpdateOption(); - $$->case_idx_ = CASE0; - } - |SET NULL { - $$ = new OnUpdateOption(); - $$->case_idx_ = CASE1; - } - |NO ACTION { - $$ = new OnUpdateOption(); - $$->case_idx_ = CASE2; - } - |SET DEFAULT { - $$ = new OnUpdateOption(); - $$->case_idx_ = CASE3; - } - ; - -key_list: - key_part { - $$ = new KeyList(); - $$->case_idx_ = CASE0; - - $$->key_part_ = $1; - } - |key_part OP_COMMA key_list { - $$ = new KeyList(); - $$->case_idx_ = CASE1; - - $$->key_part_ = $1; - $$->key_list_ = $3; - } - ; - -key_list_with_expression: - key_part_with_expression { - $$ = new KeyListWithExpression(); - $$->case_idx_ = CASE0; - - $$->key_part_with_expression_ = $1; - } - |key_part_with_expression OP_COMMA key_list_with_expression { - $$ = new KeyListWithExpression(); - $$->case_idx_ = CASE1; - - $$->key_part_with_expression_ = $1; - $$->key_list_with_expression_ = $3; - } - ; - -key_part_with_expression: - key_part { - $$ = new KeyPartWithExpression(); - $$->case_idx_ = CASE0; - - $$->key_part_ = $1; - } - |OP_LP expr_root OP_RP opt_ordering_direction { - $$ = new KeyPartWithExpression(); - $$->case_idx_ = CASE1; - - $$->expr_root_ = $2; - $$->opt_ordering_direction_ = $4; - } - ; - -key_part: - column_name opt_ordering_direction { - $$ = new KeyPart(); - $$->case_idx_ = CASE0; - - $$->column_name_ = $1; - $$->opt_ordering_direction_ = $2; - } - |column_name OP_LP iconst OP_RP opt_ordering_direction { - $$ = new KeyPart(); - $$->case_idx_ = CASE1; - - $$->column_name_ = $1; - $$->iconst_ = $3; - $$->opt_ordering_direction_ = $5; - } - ; - -constraint_key_type: - PRIMARY KEY { - $$ = new ConstraintKeyType(); - $$->case_idx_ = CASE0; - } - |UNIQUE { - $$ = new ConstraintKeyType(); - $$->case_idx_ = CASE1; - } - ; - -opt_index_name: - { - $$ = new OptIndexName(); - $$->case_idx_ = CASE0; - } - |index_name { - $$ = new OptIndexName(); - $$->case_idx_ = CASE1; - - $$->index_name_ = $1; - } - ; - -select_stmt: - query_expression { - $$ = new SelectStmt(); - $$->case_idx_ = CASE0; - - $$->query_expression_ = $1; - } - ; - -query_expression: - query_expression_body opt_order_clause opt_limit_clause { - $$ = new QueryExpression(); - $$->case_idx_ = CASE0; - - $$->query_expression_body_ = $1; - $$->opt_order_clause_ = $2; - $$->opt_limit_clause_ = $3; - } - |with_clause query_expression_body opt_order_clause opt_limit_clause { - $$ = new QueryExpression(); - $$->case_idx_ = CASE1; - - $$->with_clause_ = $1; - $$->query_expression_body_ = $2; - $$->opt_order_clause_ = $3; - $$->opt_limit_clause_ = $4; - } - ; - -query_expression_body: - query_primary { - $$ = new QueryExpressionBody(); - $$->case_idx_ = CASE0; - - $$->query_primary_ = $1; - } - |query_expression_parens %prec SUBQUERY_AS_EXPR { - $$ = new QueryExpressionBody(); - $$->case_idx_ = CASE1; - - $$->query_expression_parens_ = $1; - } - |query_expression_body UNION opt_union_option query_expression_body { - $$ = new QueryExpressionBody(); - $$->case_idx_ = CASE2; - - $$->query_expression_body_1_ = $1; - $$->opt_union_option_ = $3; - $$->query_expression_body_2_ = $4; - } - |query_expression_body EXCEPT opt_union_option query_expression_body { - $$ = new QueryExpressionBody(); - $$->case_idx_ = CASE3; - - $$->query_expression_body_1_ = $1; - $$->opt_union_option_ = $3; - $$->query_expression_body_2_ = $4; - } - |query_expression_body INTERSECT opt_union_option query_expression_body { - $$ = new QueryExpressionBody(); - $$->case_idx_ = CASE4; - - $$->query_expression_body_1_ = $1; - $$->opt_union_option_ = $3; - $$->query_expression_body_2_ = $4; - } - ; - -query_primary: - query_specification { - $$ = new QueryPrimary(); - $$->case_idx_ = CASE0; - - $$->query_specification_ = $1; - } - ; - -query_specification: - SELECT opt_select_options select_item_list opt_from_clause opt_where_clause opt_group_clause opt_having_clause opt_window_clause { - $$ = new QuerySpecification(); - $$->case_idx_ = CASE0; - - $$->opt_select_options_ = $2; - $$->select_item_list_ = $3; - $$->opt_from_clause_ = $4; - $$->opt_where_clause_ = $5; - $$->opt_group_clause_ = $6; - $$->opt_having_clause_ = $7; - $$->opt_window_clause_ = $8; - } - ; - -opt_window_clause: - { - $$ = new OptWindowClause(); - $$->case_idx_ = CASE0; - } - |WINDOW window_definition_list { - $$ = new OptWindowClause(); - $$->case_idx_ = CASE1; - - $$->window_definition_list_ = $2; - } - ; - -window_definition_list: - window_definition { - $$ = new WindowDefinitionList(); - $$->case_idx_ = CASE0; - - $$->window_definition_ = $1; - } - |window_definition OP_COMMA window_definition_list { - $$ = new WindowDefinitionList(); - $$->case_idx_ = CASE1; - - $$->window_definition_ = $1; - $$->window_definition_list_ = $3; - } - ; - -window_definition: - window_name AS window_spec { - $$ = new WindowDefinition(); - $$->case_idx_ = CASE0; - - $$->window_name_ = $1; - $$->window_spec_ = $3; - } - ; - -window_spec: - OP_LP window_spec_details OP_RP { - $$ = new WindowSpec(); - $$->case_idx_ = CASE0; - - $$->window_spec_details_ = $2; - } - ; - -window_spec_details: - opt_existing_window_name opt_partition_clause opt_window_order_by_clause opt_window_frame_clause { - $$ = new WindowSpecDetails(); - $$->case_idx_ = CASE0; - - $$->opt_existing_window_name_ = $1; - $$->opt_partition_clause_ = $2; - $$->opt_window_order_by_clause_ = $3; - $$->opt_window_frame_clause_ = $4; - } - ; - -opt_existing_window_name: - { - $$ = new OptExistingWindowName(); - $$->case_idx_ = CASE0; - } - |window_name { - $$ = new OptExistingWindowName(); - $$->case_idx_ = CASE1; - - $$->window_name_ = $1; - } - ; - -opt_partition_clause: - { - $$ = new OptPartitionClause(); - $$->case_idx_ = CASE0; - } - |PARTITION BY expr_root_list { - $$ = new OptPartitionClause(); - $$->case_idx_ = CASE1; - - $$->expr_root_list_ = $3; - } - ; - -opt_window_order_by_clause: - { - $$ = new OptWindowOrderByClause(); - $$->case_idx_ = CASE0; - } - |ORDER BY order_list { - $$ = new OptWindowOrderByClause(); - $$->case_idx_ = CASE1; - - $$->order_list_ = $3; - } - ; - -order_list: - order_expr { - $$ = new OrderList(); - $$->case_idx_ = CASE0; - - $$->order_expr_ = $1; - } - |order_expr OP_COMMA order_list { - $$ = new OrderList(); - $$->case_idx_ = CASE1; - - $$->order_expr_ = $1; - $$->order_list_ = $3; - } - ; - -order_expr: - expr_root opt_ordering_direction { - $$ = new OrderExpr(); - $$->case_idx_ = CASE0; - - $$->expr_root_ = $1; - $$->opt_ordering_direction_ = $2; - } - ; - -opt_ordering_direction: - { - $$ = new OptOrderingDirection(); - $$->case_idx_ = CASE0; - } - |ASC { - $$ = new OptOrderingDirection(); - $$->case_idx_ = CASE1; - } - |DESC { - $$ = new OptOrderingDirection(); - $$->case_idx_ = CASE2; - } - ; - -opt_window_frame_clause: - { - $$ = new OptWindowFrameClause(); - $$->case_idx_ = CASE0; - } - |window_frame_units window_frame_extent { - $$ = new OptWindowFrameClause(); - $$->case_idx_ = CASE1; - - $$->window_frame_units_ = $1; - $$->window_frame_extent_ = $2; - } - ; - -window_frame_units: - ROWS { - $$ = new WindowFrameUnits(); - $$->case_idx_ = CASE0; - } - |RANGE { - $$ = new WindowFrameUnits(); - $$->case_idx_ = CASE1; - } - ; - -window_frame_extent: - window_frame_start { - $$ = new WindowFrameExtent(); - $$->case_idx_ = CASE0; - - $$->window_frame_start_ = $1; - } - |window_frame_between { - $$ = new WindowFrameExtent(); - $$->case_idx_ = CASE1; - - $$->window_frame_between_ = $1; - } - ; - -window_frame_start: - UNBOUNDED PRECEDING { - $$ = new WindowFrameStart(); - $$->case_idx_ = CASE0; - } - |iconst PRECEDING { - $$ = new WindowFrameStart(); - $$->case_idx_ = CASE1; - - $$->iconst_ = $1; - } - |CURRENT ROW { - $$ = new WindowFrameStart(); - $$->case_idx_ = CASE2; - } - ; - -window_frame_between: - BETWEEN window_frame_start AND window_frame_bound { - $$ = new WindowFrameBetween(); - $$->case_idx_ = CASE0; - - $$->window_frame_start_ = $2; - $$->window_frame_bound_ = $4; - } - ; - -window_frame_bound: - window_frame_start { - $$ = new WindowFrameBound(); - $$->case_idx_ = CASE0; - - $$->window_frame_start_ = $1; - } - |UNBOUNDED FOLLOWING { - $$ = new WindowFrameBound(); - $$->case_idx_ = CASE1; - } - |iconst FOLLOWING { - $$ = new WindowFrameBound(); - $$->case_idx_ = CASE2; - - $$->iconst_ = $1; - } - ; - -opt_having_clause: - { - $$ = new OptHavingClause(); - $$->case_idx_ = CASE0; - } - |HAVING expr_root { - $$ = new OptHavingClause(); - $$->case_idx_ = CASE1; - - $$->expr_root_ = $2; - } - ; - -opt_group_clause: - { - $$ = new OptGroupClause(); - $$->case_idx_ = CASE0; - } - |GROUP BY expr_root_list olap_opt { - $$ = new OptGroupClause(); - $$->case_idx_ = CASE1; - - $$->expr_root_list_ = $3; - $$->olap_opt_ = $4; - } - ; - -olap_opt: - { - $$ = new OlapOpt(); - $$->case_idx_ = CASE0; - } - |WITH ROLLUP { - $$ = new OlapOpt(); - $$->case_idx_ = CASE1; - } - ; - -opt_where_clause: - { - $$ = new OptWhereClause(); - $$->case_idx_ = CASE0; - } - |where_clause { - $$ = new OptWhereClause(); - $$->case_idx_ = CASE1; - - $$->where_clause_ = $1; - } - ; - -where_clause: - WHERE expr_root { - $$ = new WhereClause(); - $$->case_idx_ = CASE0; - - $$->expr_root_ = $2; - } - ; - -opt_from_clause: - { - $$ = new OptFromClause(); - $$->case_idx_ = CASE0; - } - |from_clause { - $$ = new OptFromClause(); - $$->case_idx_ = CASE1; - - $$->from_clause_ = $1; - } - ; - -from_clause: - FROM table_reference_list { - $$ = new FromClause(); - $$->case_idx_ = CASE0; - - $$->table_reference_list_ = $2; - } - ; - -table_reference_list: - table_reference { - $$ = new TableReferenceList(); - $$->case_idx_ = CASE0; - - $$->table_reference_ = $1; - } - |table_reference OP_COMMA table_reference_list { - $$ = new TableReferenceList(); - $$->case_idx_ = CASE1; - - $$->table_reference_ = $1; - $$->table_reference_list_ = $3; - } - ; - -table_reference: - table_factor { - $$ = new TableReference(); - $$->case_idx_ = CASE0; - - $$->table_factor_ = $1; - } - |joined_table { - $$ = new TableReference(); - $$->case_idx_ = CASE1; - - $$->joined_table_ = $1; - } - ; - -table_factor: - single_table { - $$ = new TableFactor(); - $$->case_idx_ = CASE0; - - $$->single_table_ = $1; - } - |derived_table { - $$ = new TableFactor(); - $$->case_idx_ = CASE1; - - $$->derived_table_ = $1; - } - |joined_table_parens { - $$ = new TableFactor(); - $$->case_idx_ = CASE2; - - $$->joined_table_parens_ = $1; - } - |table_reference_list_parens { - $$ = new TableFactor(); - $$->case_idx_ = CASE3; - - $$->table_reference_list_parens_ = $1; - } - ; - -table_reference_list_parens: - OP_LP table_reference OP_COMMA table_reference_list OP_RP { - $$ = new TableReferenceListParens(); - $$->case_idx_ = CASE0; - - $$->table_reference_ = $2; - $$->table_reference_list_ = $4; - } - ; - -joined_table_parens: - OP_LP joined_table OP_RP { - $$ = new JoinedTableParens(); - $$->case_idx_ = CASE0; - - $$->joined_table_ = $2; - } - ; - -derived_table: - subquery AS alias opt_column_list { - $$ = new DerivedTable(); - $$->case_idx_ = CASE0; - - $$->subquery_ = $1; - $$->alias_ = $3; - $$->opt_column_list_ = $4; - } - |LATERAL subquery AS alias opt_column_list { - $$ = new DerivedTable(); - $$->case_idx_ = CASE1; - - $$->subquery_ = $2; - $$->alias_ = $4; - $$->opt_column_list_ = $5; - } - ; - -opt_column_list: - { - $$ = new OptColumnList(); - $$->case_idx_ = CASE0; - } - |OP_LP column_list OP_RP { - $$ = new OptColumnList(); - $$->case_idx_ = CASE1; - - $$->column_list_ = $2; - } - ; - -column_list: - column_name { - $$ = new ColumnList(); - $$->case_idx_ = CASE0; - - $$->column_name_ = $1; - } - |column_name OP_COMMA column_list { - $$ = new ColumnList(); - $$->case_idx_ = CASE1; - - $$->column_name_ = $1; - $$->column_list_ = $3; - } - ; - -subquery: - query_expression_parens %prec SUBQUERY_AS_EXPR { - $$ = new Subquery(); - $$->case_idx_ = CASE0; - - $$->query_expression_parens_ = $1; - } - ; - -single_table: - table_name opt_alias { - $$ = new SingleTable(); - $$->case_idx_ = CASE0; - - $$->table_name_ = $1; - $$->opt_alias_ = $2; - } - ; - -opt_alias: - { - $$ = new OptAlias(); - $$->case_idx_ = CASE0; - } - |AS alias { - $$ = new OptAlias(); - $$->case_idx_ = CASE1; - - $$->alias_ = $2; - } - ; - -joined_table: - table_reference inner_join_type table_reference ON expr_root { - $$ = new JoinedTable(); - $$->case_idx_ = CASE0; - - $$->table_reference_1_ = $1; - $$->inner_join_type_ = $2; - $$->table_reference_2_ = $3; - $$->expr_root_ = $5; - } - |table_reference inner_join_type table_reference USING OP_LP column_list OP_RP { - $$ = new JoinedTable(); - $$->case_idx_ = CASE1; - - $$->table_reference_1_ = $1; - $$->inner_join_type_ = $2; - $$->table_reference_2_ = $3; - $$->column_list_ = $6; - } - |table_reference outer_join_type table_reference ON expr_root { - $$ = new JoinedTable(); - $$->case_idx_ = CASE2; - - $$->table_reference_1_ = $1; - $$->outer_join_type_ = $2; - $$->table_reference_2_ = $3; - $$->expr_root_ = $5; - } - |table_reference outer_join_type table_reference USING OP_LP column_list OP_RP { - $$ = new JoinedTable(); - $$->case_idx_ = CASE3; - - $$->table_reference_1_ = $1; - $$->outer_join_type_ = $2; - $$->table_reference_2_ = $3; - $$->column_list_ = $6; - } - |table_reference inner_join_type table_reference %prec CONDITIONLESS_JOIN { - $$ = new JoinedTable(); - $$->case_idx_ = CASE4; - - $$->table_reference_1_ = $1; - $$->inner_join_type_ = $2; - $$->table_reference_2_ = $3; - } - |table_reference natural_join_type table_factor { - $$ = new JoinedTable(); - $$->case_idx_ = CASE5; - - $$->table_reference_1_ = $1; - $$->natural_join_type_ = $2; - $$->table_factor_ = $3; - } - ; - -inner_join_type: - JOIN { - $$ = new InnerJoinType(); - $$->case_idx_ = CASE0; - } - |INNER JOIN { - $$ = new InnerJoinType(); - $$->case_idx_ = CASE1; - } - |CROSS JOIN { - $$ = new InnerJoinType(); - $$->case_idx_ = CASE2; - } - |STRAIGHT_JOIN { - $$ = new InnerJoinType(); - $$->case_idx_ = CASE3; - } - ; - -natural_join_type: - NATURAL opt_inner JOIN { - $$ = new NaturalJoinType(); - $$->case_idx_ = CASE0; - - $$->opt_inner_ = $2; - } - |NATURAL RIGHT opt_outer JOIN { - $$ = new NaturalJoinType(); - $$->case_idx_ = CASE1; - - $$->opt_outer_ = $3; - } - |NATURAL LEFT opt_outer JOIN { - $$ = new NaturalJoinType(); - $$->case_idx_ = CASE2; - - $$->opt_outer_ = $3; - } - ; - -opt_inner: - { - $$ = new OptInner(); - $$->case_idx_ = CASE0; - } - |INNER { - $$ = new OptInner(); - $$->case_idx_ = CASE1; - } - ; - -opt_outer: - { - $$ = new OptOuter(); - $$->case_idx_ = CASE0; - } - |OUTER { - $$ = new OptOuter(); - $$->case_idx_ = CASE1; - } - ; - -outer_join_type: - LEFT opt_outer JOIN { - $$ = new OuterJoinType(); - $$->case_idx_ = CASE0; - - $$->opt_outer_ = $2; - } - |RIGHT opt_outer JOIN { - $$ = new OuterJoinType(); - $$->case_idx_ = CASE1; - - $$->opt_outer_ = $2; - } - ; - -select_item_list: - select_item { - $$ = new SelectItemList(); - $$->case_idx_ = CASE0; - - $$->select_item_ = $1; - } - |select_item OP_COMMA select_item_list { - $$ = new SelectItemList(); - $$->case_idx_ = CASE1; - - $$->select_item_ = $1; - $$->select_item_list_ = $3; - } - ; - -select_item: - table_wild { - $$ = new SelectItem(); - $$->case_idx_ = CASE0; - - $$->table_wild_ = $1; - } - |expr_root opt_alias { - $$ = new SelectItem(); - $$->case_idx_ = CASE1; - - $$->expr_root_ = $1; - $$->opt_alias_ = $2; - } - ; - -table_wild: - OP_MUL { - $$ = new TableWild(); - $$->case_idx_ = CASE0; - } - |table_name OP_DOT OP_MUL { - $$ = new TableWild(); - $$->case_idx_ = CASE1; - - $$->table_name_ = $1; - } - ; - -opt_select_options: - { - $$ = new OptSelectOptions(); - $$->case_idx_ = CASE0; - } - |select_option_list { - $$ = new OptSelectOptions(); - $$->case_idx_ = CASE1; - - $$->select_option_list_ = $1; - } - ; - -select_option_list: - select_option { - $$ = new SelectOptionList(); - $$->case_idx_ = CASE0; - - $$->select_option_ = $1; - } - |select_option select_option_list { - $$ = new SelectOptionList(); - $$->case_idx_ = CASE1; - - $$->select_option_ = $1; - $$->select_option_list_ = $2; - } - ; - -select_option: - SQL_NO_CACHE { - $$ = new SelectOption(); - $$->case_idx_ = CASE0; - } - |STRAIGHT_JOIN { - $$ = new SelectOption(); - $$->case_idx_ = CASE1; - } - |HIGH_PRIORITY { - $$ = new SelectOption(); - $$->case_idx_ = CASE2; - } - |DISTINCT { - $$ = new SelectOption(); - $$->case_idx_ = CASE3; - } - |SQL_SMALL_RESULT { - $$ = new SelectOption(); - $$->case_idx_ = CASE4; - } - |SQL_BIG_RESULT { - $$ = new SelectOption(); - $$->case_idx_ = CASE5; - } - |SQL_BUFFER_RESULT { - $$ = new SelectOption(); - $$->case_idx_ = CASE6; - } - |SQL_CALC_FOUND_ROWS { - $$ = new SelectOption(); - $$->case_idx_ = CASE7; - } - |ALL { - $$ = new SelectOption(); - $$->case_idx_ = CASE8; - } - ; - -query_expression_parens: - OP_LP query_expression_parens OP_RP { - $$ = new QueryExpressionParens(); - $$->case_idx_ = CASE0; - - $$->query_expression_parens_ = $2; - } - |OP_LP query_expression OP_RP { - $$ = new QueryExpressionParens(); - $$->case_idx_ = CASE1; - - $$->query_expression_ = $2; - } - ; - -opt_union_option: - { - $$ = new OptUnionOption(); - $$->case_idx_ = CASE0; - } - |DISTINCT { - $$ = new OptUnionOption(); - $$->case_idx_ = CASE1; - } - |ALL { - $$ = new OptUnionOption(); - $$->case_idx_ = CASE2; - } - ; - -opt_order_clause: - { - $$ = new OptOrderClause(); - $$->case_idx_ = CASE0; - } - |order_clause { - $$ = new OptOrderClause(); - $$->case_idx_ = CASE1; - - $$->order_clause_ = $1; - } - ; - -order_clause: - ORDER BY order_list { - $$ = new OrderClause(); - $$->case_idx_ = CASE0; - - $$->order_list_ = $3; - } - ; - -opt_limit_clause: - { - $$ = new OptLimitClause(); - $$->case_idx_ = CASE0; - } - |limit_clause { - $$ = new OptLimitClause(); - $$->case_idx_ = CASE1; - - $$->limit_clause_ = $1; - } - ; - -limit_clause: - LIMIT limit_options { - $$ = new LimitClause(); - $$->case_idx_ = CASE0; - - $$->limit_options_ = $2; - } - ; - -limit_options: - iconst { - $$ = new LimitOptions(); - $$->case_idx_ = CASE0; - - $$->iconst_1_ = $1; - } - |iconst OP_COMMA iconst { - $$ = new LimitOptions(); - $$->case_idx_ = CASE1; - - $$->iconst_1_ = $1; - $$->iconst_2_ = $3; - } - ; - -with_clause: - WITH with_list { - $$ = new WithClause(); - $$->case_idx_ = CASE0; - - $$->with_list_ = $2; - } - |WITH RECURSIVE with_list { - $$ = new WithClause(); - $$->case_idx_ = CASE1; - - $$->with_list_ = $3; - } - ; - -with_list: - common_table_expr { - $$ = new WithList(); - $$->case_idx_ = CASE0; - - $$->common_table_expr_ = $1; - } - |common_table_expr OP_COMMA with_list { - $$ = new WithList(); - $$->case_idx_ = CASE1; - - $$->common_table_expr_ = $1; - $$->with_list_ = $3; - } - ; - -common_table_expr: - table_name opt_column_list AS subquery { - $$ = new CommonTableExpr(); - $$->case_idx_ = CASE0; - - $$->table_name_ = $1; - $$->opt_column_list_ = $2; - $$->subquery_ = $4; - } - ; - -expr_root_list: - expr_root { - $$ = new ExprRootList(); - $$->case_idx_ = CASE0; - - $$->expr_root_ = $1; - } - |expr_root OP_COMMA expr_root_list { - $$ = new ExprRootList(); - $$->case_idx_ = CASE1; - - $$->expr_root_ = $1; - $$->expr_root_list_ = $3; - } - ; - -expr_root: - expr { - $$ = new ExprRoot(); - $$->case_idx_ = CASE0; - - $$->expr_ = $1; - } - ; - -expr: - expr OR expr { - $$ = new Expr(); - $$->case_idx_ = CASE0; - - $$->expr_1_ = $1; - $$->expr_2_ = $3; - } - |expr XOR expr { - $$ = new Expr(); - $$->case_idx_ = CASE1; - - $$->expr_1_ = $1; - $$->expr_2_ = $3; - } - |expr AND expr { - $$ = new Expr(); - $$->case_idx_ = CASE2; - - $$->expr_1_ = $1; - $$->expr_2_ = $3; - } - |NOT expr { - $$ = new Expr(); - $$->case_idx_ = CASE3; - - $$->expr_1_ = $2; - } - |bool_pri IS TRUE { - $$ = new Expr(); - $$->case_idx_ = CASE4; - - $$->bool_pri_ = $1; - } - |bool_pri IS NOT TRUE { - $$ = new Expr(); - $$->case_idx_ = CASE5; - - $$->bool_pri_ = $1; - } - |bool_pri IS FALSE { - $$ = new Expr(); - $$->case_idx_ = CASE6; - - $$->bool_pri_ = $1; - } - |bool_pri IS NOT FALSE { - $$ = new Expr(); - $$->case_idx_ = CASE7; - - $$->bool_pri_ = $1; - } - |bool_pri IS UNKNOWN { - $$ = new Expr(); - $$->case_idx_ = CASE8; - - $$->bool_pri_ = $1; - } - |bool_pri IS NOT UNKNOWN { - $$ = new Expr(); - $$->case_idx_ = CASE9; - - $$->bool_pri_ = $1; - } - |bool_pri { - $$ = new Expr(); - $$->case_idx_ = CASE10; - - $$->bool_pri_ = $1; - } - ; - -bool_pri: - bool_pri IS NULL { - $$ = new BoolPri(); - $$->case_idx_ = CASE0; - - $$->bool_pri_ = $1; - } - |bool_pri IS NOT NULL { - $$ = new BoolPri(); - $$->case_idx_ = CASE1; - - $$->bool_pri_ = $1; - } - |bool_pri comp_op predicate { - $$ = new BoolPri(); - $$->case_idx_ = CASE2; - - $$->bool_pri_ = $1; - $$->comp_op_ = $2; - $$->predicate_ = $3; - } - |bool_pri comp_op all_subquery { - $$ = new BoolPri(); - $$->case_idx_ = CASE3; - - $$->bool_pri_ = $1; - $$->comp_op_ = $2; - $$->all_subquery_ = $3; - } - |predicate { - $$ = new BoolPri(); - $$->case_idx_ = CASE4; - - $$->predicate_ = $1; - } - ; - -predicate: - bit_expr in_subquery { - $$ = new Predicate(); - $$->case_idx_ = CASE0; - - $$->bit_expr_1_ = $1; - $$->in_subquery_ = $2; - } - |bit_expr IN OP_LP expr OP_RP { - $$ = new Predicate(); - $$->case_idx_ = CASE1; - - $$->bit_expr_1_ = $1; - $$->expr_ = $4; - } - |bit_expr IN OP_LP expr OP_COMMA expr_list OP_RP { - $$ = new Predicate(); - $$->case_idx_ = CASE2; - - $$->bit_expr_1_ = $1; - $$->expr_ = $4; - $$->expr_list_ = $6; - } - |bit_expr NOT IN OP_LP expr OP_RP { - $$ = new Predicate(); - $$->case_idx_ = CASE3; - - $$->bit_expr_1_ = $1; - $$->expr_ = $5; - } - |bit_expr NOT IN OP_LP expr OP_COMMA expr_list OP_RP { - $$ = new Predicate(); - $$->case_idx_ = CASE4; - - $$->bit_expr_1_ = $1; - $$->expr_ = $5; - $$->expr_list_ = $7; - } - |bit_expr BETWEEN bit_expr AND predicate { - $$ = new Predicate(); - $$->case_idx_ = CASE5; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - $$->predicate_ = $5; - } - |bit_expr NOT BETWEEN bit_expr AND predicate { - $$ = new Predicate(); - $$->case_idx_ = CASE6; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $4; - $$->predicate_ = $6; - } - |bit_expr SOUNDS LIKE bit_expr { - $$ = new Predicate(); - $$->case_idx_ = CASE7; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $4; - } - |bit_expr LIKE simple_expr { - $$ = new Predicate(); - $$->case_idx_ = CASE8; - - $$->bit_expr_1_ = $1; - $$->simple_expr_ = $3; - } - |bit_expr NOT LIKE simple_expr { - $$ = new Predicate(); - $$->case_idx_ = CASE9; - - $$->bit_expr_1_ = $1; - $$->simple_expr_ = $4; - } - |bit_expr REGEXP bit_expr { - $$ = new Predicate(); - $$->case_idx_ = CASE10; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr NOT REGEXP bit_expr { - $$ = new Predicate(); - $$->case_idx_ = CASE11; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $4; - } - |bit_expr { - $$ = new Predicate(); - $$->case_idx_ = CASE12; - - $$->bit_expr_1_ = $1; - } - ; - -bit_expr: - bit_expr OP_OR bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE0; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_AND bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE1; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_SHL bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE2; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_SHR bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE3; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_ADD bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE4; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_SUB bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE5; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_MUL bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE6; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_DIVIDE bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE7; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_MOD bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE8; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |bit_expr OP_XOR bit_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE9; - - $$->bit_expr_1_ = $1; - $$->bit_expr_2_ = $3; - } - |simple_expr { - $$ = new BitExpr(); - $$->case_idx_ = CASE10; - - $$->simple_expr_ = $1; - } - ; - -simple_expr: - columnref { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE0; - - $$->columnref_ = $1; - } - |literal { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE1; - - $$->literal_ = $1; - } - |iconst { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE2; - - $$->iconst_ = $1; - } - |fconst { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE3; - - $$->fconst_ = $1; - } - |sconst { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE4; - - $$->sconst_ = $1; - } - |OP_ADD simple_expr %prec UMINUS { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE5; - - $$->simple_expr_ = $2; - } - |OP_SUB simple_expr %prec UMINUS { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE6; - - $$->simple_expr_ = $2; - } - |OP_NOT simple_expr %prec UMINUS { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE7; - - $$->simple_expr_ = $2; - } - |subquery { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE8; - - $$->subquery_ = $1; - } - |EXISTS subquery { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE9; - - $$->subquery_ = $2; - } - |type_cast { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE10; - - $$->type_cast_ = $1; - } - |case_expr { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE11; - - $$->case_expr_ = $1; - } - |DEFAULT OP_LP columnref OP_RP { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE12; - - $$->columnref_ = $3; - } - |function { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE13; - - $$->function_ = $1; - } - |OP_LP expr OP_RP { - $$ = new SimpleExpr(); - $$->case_idx_ = CASE14; - - $$->expr_ = $2; - } - ; - -function: - control_function { - $$ = new Function(); - $$->case_idx_ = CASE0; - - $$->control_function_ = $1; - } - |math_function { - $$ = new Function(); - $$->case_idx_ = CASE1; - - $$->math_function_ = $1; - } - |string_function { - $$ = new Function(); - $$->case_idx_ = CASE2; - - $$->string_function_ = $1; - } - |aggregate_function { - $$ = new Function(); - $$->case_idx_ = CASE3; - - $$->aggregate_function_ = $1; - } - |window_function { - $$ = new Function(); - $$->case_idx_ = CASE4; - - $$->window_function_ = $1; - } - ; - -string_function: - ASCII OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE0; - - $$->expr_1_ = $3; - } - |BIN OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE1; - - $$->expr_1_ = $3; - } - |BIT_LENGTH OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE2; - - $$->expr_1_ = $3; - } - |CHAR_LENGTH OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE3; - - $$->expr_1_ = $3; - } - |LENGTH OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE4; - - $$->expr_1_ = $3; - } - |LOWER OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE5; - - $$->expr_1_ = $3; - } - |LTRIM OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE6; - - $$->expr_1_ = $3; - } - |OCT OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE7; - - $$->expr_1_ = $3; - } - |ORD OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE8; - - $$->expr_1_ = $3; - } - |QUOTE OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE9; - - $$->expr_1_ = $3; - } - |REVERSE OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE10; - - $$->expr_1_ = $3; - } - |RTRIM OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE11; - - $$->expr_1_ = $3; - } - |SPACE OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE12; - - $$->expr_1_ = $3; - } - |TRIM OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE13; - - $$->expr_1_ = $3; - } - |TRIM OP_LP LEADING FROM expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE14; - - $$->expr_1_ = $5; - } - |TRIM OP_LP TRAILING FROM expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE15; - - $$->expr_1_ = $5; - } - |UNHEX OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE16; - - $$->expr_1_ = $3; - } - |UPPER OP_LP expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE17; - - $$->expr_1_ = $3; - } - |FIND_IN_SET OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE18; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |INSTR OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE19; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |LEFT OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE20; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |LOCATE OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE21; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |REPEAT OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE22; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |RIGHT OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE23; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |SUBSTRING OP_LP expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE24; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |TRIM OP_LP LEADING expr FROM expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE25; - - $$->expr_1_ = $4; - $$->expr_2_ = $6; - } - |TRIM OP_LP TRAILING expr FROM expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE26; - - $$->expr_1_ = $4; - $$->expr_2_ = $6; - } - |TRIM OP_LP expr FROM expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE27; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |EXPORT_SET OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE28; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |LOCATE OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE29; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |LPAD OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE30; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |REPLACE OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE31; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |RPAD OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE32; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |SUBSTRING OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE33; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |SUBSTRING_INDEX OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE34; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |EXPORT_SET OP_LP expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE35; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - $$->expr_4_ = $9; - } - |INSERT OP_LP expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE36; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - $$->expr_4_ = $9; - } - |EXPORT_SET OP_LP expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE37; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - $$->expr_4_ = $9; - $$->expr_5_ = $11; - } - |CHAR OP_LP expr_list OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE38; - - $$->expr_list_ = $3; - } - |CONCAT OP_LP expr_list OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE39; - - $$->expr_list_ = $3; - } - |CONCAT_WS OP_LP expr OP_COMMA expr_list OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE40; - - $$->expr_1_ = $3; - $$->expr_list_ = $5; - } - |ELT OP_LP expr OP_COMMA expr_list OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE41; - - $$->expr_1_ = $3; - $$->expr_list_ = $5; - } - |FIELD OP_LP expr OP_COMMA expr_list OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE42; - - $$->expr_1_ = $3; - $$->expr_list_ = $5; - } - |MAKE_SET OP_LP expr OP_COMMA expr_list OP_RP { - $$ = new StringFunction(); - $$->case_idx_ = CASE43; - - $$->expr_1_ = $3; - $$->expr_list_ = $5; - } - ; - -math_function: - PI OP_LP OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE0; - } - |RAND OP_LP OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE1; - } - |ABS OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE2; - - $$->expr_1_ = $3; - } - |ACOS OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE3; - - $$->expr_1_ = $3; - } - |ASIN OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE4; - - $$->expr_1_ = $3; - } - |ATAN OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE5; - - $$->expr_1_ = $3; - } - |CEILING OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE6; - - $$->expr_1_ = $3; - } - |COS OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE7; - - $$->expr_1_ = $3; - } - |COT OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE8; - - $$->expr_1_ = $3; - } - |DEGREES OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE9; - - $$->expr_1_ = $3; - } - |EXP OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE10; - - $$->expr_1_ = $3; - } - |FLOOR OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE11; - - $$->expr_1_ = $3; - } - |HEX OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE12; - - $$->expr_1_ = $3; - } - |LN OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE13; - - $$->expr_1_ = $3; - } - |RADIANS OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE14; - - $$->expr_1_ = $3; - } - |RAND OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE15; - - $$->expr_1_ = $3; - } - |ROUND OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE16; - - $$->expr_1_ = $3; - } - |SIGN OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE17; - - $$->expr_1_ = $3; - } - |SIN OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE18; - - $$->expr_1_ = $3; - } - |SQRT OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE19; - - $$->expr_1_ = $3; - } - |TAN OP_LP expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE20; - - $$->expr_1_ = $3; - } - |ATAN OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE21; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |FORMAT OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE22; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |LOG OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE23; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |MOD OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE24; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |POW OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE25; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |ROUND OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE26; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |TRUNCATE OP_LP expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE27; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |CONV OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new MathFunction(); - $$->case_idx_ = CASE28; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - ; - -window_function: - ROW_NUMBER OP_LP OP_RP windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE0; - - $$->windowing_clause_ = $4; - } - |RANK OP_LP OP_RP windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE1; - - $$->windowing_clause_ = $4; - } - |DENSE_RANK OP_LP OP_RP windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE2; - - $$->windowing_clause_ = $4; - } - |CUME_DIST OP_LP OP_RP windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE3; - - $$->windowing_clause_ = $4; - } - |PERCENT_RANK OP_LP OP_RP windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE4; - - $$->windowing_clause_ = $4; - } - |NTILE OP_LP iconst OP_RP windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE5; - - $$->iconst_ = $3; - $$->windowing_clause_ = $5; - } - |LEAD OP_LP expr opt_lead_lag_info OP_RP opt_null_treatment windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE6; - - $$->expr_ = $3; - $$->opt_lead_lag_info_ = $4; - $$->opt_null_treatment_ = $6; - $$->windowing_clause_ = $7; - } - |LAG OP_LP expr opt_lead_lag_info OP_RP opt_null_treatment windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE7; - - $$->expr_ = $3; - $$->opt_lead_lag_info_ = $4; - $$->opt_null_treatment_ = $6; - $$->windowing_clause_ = $7; - } - |FIRST_VALUE OP_LP expr OP_RP opt_null_treatment windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE8; - - $$->expr_ = $3; - $$->opt_null_treatment_ = $5; - $$->windowing_clause_ = $6; - } - |LAST_VALUE OP_LP expr OP_RP opt_null_treatment windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE9; - - $$->expr_ = $3; - $$->opt_null_treatment_ = $5; - $$->windowing_clause_ = $6; - } - |NTH_VALUE OP_LP expr OP_COMMA iconst OP_RP opt_from_first_last opt_null_treatment windowing_clause { - $$ = new WindowFunction(); - $$->case_idx_ = CASE10; - - $$->expr_ = $3; - $$->iconst_ = $5; - $$->opt_from_first_last_ = $7; - $$->opt_null_treatment_ = $8; - $$->windowing_clause_ = $9; - } - ; - -opt_null_treatment: - { - $$ = new OptNullTreatment(); - $$->case_idx_ = CASE0; - } - |RESPECT NULLS { - $$ = new OptNullTreatment(); - $$->case_idx_ = CASE1; - } - |IGNORE NULLS { - $$ = new OptNullTreatment(); - $$->case_idx_ = CASE2; - } - ; - -opt_from_first_last: - { - $$ = new OptFromFirstLast(); - $$->case_idx_ = CASE0; - } - |FROM FIRST { - $$ = new OptFromFirstLast(); - $$->case_idx_ = CASE1; - } - |FROM LAST { - $$ = new OptFromFirstLast(); - $$->case_idx_ = CASE2; - } - ; - -opt_lead_lag_info: - { - $$ = new OptLeadLagInfo(); - $$->case_idx_ = CASE0; - } - |lead_lag_info { - $$ = new OptLeadLagInfo(); - $$->case_idx_ = CASE1; - - $$->lead_lag_info_ = $1; - } - ; - -lead_lag_info: - OP_COMMA iconst { - $$ = new LeadLagInfo(); - $$->case_idx_ = CASE0; - - $$->iconst_ = $2; - } - |OP_COMMA iconst OP_COMMA expr { - $$ = new LeadLagInfo(); - $$->case_idx_ = CASE1; - - $$->iconst_ = $2; - $$->expr_ = $4; - } - ; - -aggregate_function: - AVG OP_LP opt_distinct expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE0; - - $$->opt_distinct_ = $3; - $$->expr_ = $4; - $$->opt_windowing_clause_ = $6; - } - |BIT_AND OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE1; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |BIT_OR OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE2; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |BIT_XOR OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE3; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |COUNT OP_LP OP_MUL OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE4; - - $$->opt_windowing_clause_ = $5; - } - |COUNT OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE5; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |COUNT OP_LP DISTINCT expr_list OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE6; - - $$->expr_list_ = $4; - $$->opt_windowing_clause_ = $6; - } - |MIN OP_LP opt_distinct expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE7; - - $$->opt_distinct_ = $3; - $$->expr_ = $4; - $$->opt_windowing_clause_ = $6; - } - |MAX OP_LP opt_distinct expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE8; - - $$->opt_distinct_ = $3; - $$->expr_ = $4; - $$->opt_windowing_clause_ = $6; - } - |SUM OP_LP opt_distinct expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE9; - - $$->opt_distinct_ = $3; - $$->expr_ = $4; - $$->opt_windowing_clause_ = $6; - } - |STD OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE10; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |STDDEV_SAMP OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE11; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |VARIANCE OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE12; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |VAR_SAMP OP_LP expr OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE13; - - $$->expr_ = $3; - $$->opt_windowing_clause_ = $5; - } - |GROUP_CONCAT OP_LP opt_distinct expr_list opt_order_clause opt_gconcat_separator OP_RP opt_windowing_clause { - $$ = new AggregateFunction(); - $$->case_idx_ = CASE14; - - $$->opt_distinct_ = $3; - $$->expr_list_ = $4; - $$->opt_order_clause_ = $5; - $$->opt_gconcat_separator_ = $6; - $$->opt_windowing_clause_ = $8; - } - ; - -opt_gconcat_separator: - { - $$ = new OptGconcatSeparator(); - $$->case_idx_ = CASE0; - } - |SEPARATOR sconst { - $$ = new OptGconcatSeparator(); - $$->case_idx_ = CASE1; - - $$->sconst_ = $2; - } - ; - -opt_distinct: - { - $$ = new OptDistinct(); - $$->case_idx_ = CASE0; - } - |DISTINCT { - $$ = new OptDistinct(); - $$->case_idx_ = CASE1; - } - ; - -opt_windowing_clause: - { - $$ = new OptWindowingClause(); - $$->case_idx_ = CASE0; - } - |windowing_clause { - $$ = new OptWindowingClause(); - $$->case_idx_ = CASE1; - - $$->windowing_clause_ = $1; - } - ; - -windowing_clause: - OVER window_name_or_spec { - $$ = new WindowingClause(); - $$->case_idx_ = CASE0; - - $$->window_name_or_spec_ = $2; - } - ; - -window_name_or_spec: - window_name { - $$ = new WindowNameOrSpec(); - $$->case_idx_ = CASE0; - - $$->window_name_ = $1; - } - |window_spec { - $$ = new WindowNameOrSpec(); - $$->case_idx_ = CASE1; - - $$->window_spec_ = $1; - } - ; - -control_function: - IF OP_LP expr OP_COMMA expr OP_COMMA expr OP_RP { - $$ = new ControlFunction(); - $$->case_idx_ = CASE0; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - $$->expr_3_ = $7; - } - |IFNULL OP_LP expr OP_COMMA expr OP_RP { - $$ = new ControlFunction(); - $$->case_idx_ = CASE1; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - |NULLIF OP_LP expr OP_COMMA expr OP_RP { - $$ = new ControlFunction(); - $$->case_idx_ = CASE2; - - $$->expr_1_ = $3; - $$->expr_2_ = $5; - } - ; - -case_expr: - CASE opt_expr when_clasue_list opt_else END { - $$ = new CaseExpr(); - $$->case_idx_ = CASE0; - - $$->opt_expr_ = $2; - $$->when_clasue_list_ = $3; - $$->opt_else_ = $4; - } - ; - -when_clasue_list: - when_list { - $$ = new WhenClasueList(); - $$->case_idx_ = CASE0; - - $$->when_list_ = $1; - } - |when_list when_clasue_list { - $$ = new WhenClasueList(); - $$->case_idx_ = CASE1; - - $$->when_list_ = $1; - $$->when_clasue_list_ = $2; - } - ; - -when_list: - WHEN expr THEN expr { - $$ = new WhenList(); - $$->case_idx_ = CASE0; - - $$->expr_1_ = $2; - $$->expr_2_ = $4; - } - ; - -opt_expr: - { - $$ = new OptExpr(); - $$->case_idx_ = CASE0; - } - |expr { - $$ = new OptExpr(); - $$->case_idx_ = CASE1; - - $$->expr_ = $1; - } - ; - -opt_else: - { - $$ = new OptElse(); - $$->case_idx_ = CASE0; - } - |ELSE expr { - $$ = new OptElse(); - $$->case_idx_ = CASE1; - - $$->expr_ = $2; - } - ; - -type_cast: - CAST OP_LP expr AS cast_type OP_RP { - $$ = new TypeCast(); - $$->case_idx_ = CASE0; - - $$->expr_ = $3; - $$->cast_type_ = $5; - } - |CONVERT OP_LP expr OP_COMMA cast_type OP_RP { - $$ = new TypeCast(); - $$->case_idx_ = CASE1; - - $$->expr_ = $3; - $$->cast_type_ = $5; - } - ; - -cast_type: - BINARY opt_field_length { - $$ = new CastType(); - $$->case_idx_ = CASE0; - - $$->opt_field_length_ = $2; - } - |CHAR opt_field_length { - $$ = new CastType(); - $$->case_idx_ = CASE1; - - $$->opt_field_length_ = $2; - } - |NCHAR opt_field_length { - $$ = new CastType(); - $$->case_idx_ = CASE2; - - $$->opt_field_length_ = $2; - } - |SIGNED { - $$ = new CastType(); - $$->case_idx_ = CASE3; - } - |UNSIGNED { - $$ = new CastType(); - $$->case_idx_ = CASE4; - } - |DECIMAL float_options { - $$ = new CastType(); - $$->case_idx_ = CASE5; - - $$->float_options_ = $2; - } - |REAL { - $$ = new CastType(); - $$->case_idx_ = CASE6; - } - |FLOAT opt_field_length { - $$ = new CastType(); - $$->case_idx_ = CASE7; - - $$->opt_field_length_ = $2; - } - ; - -float_options: - { - $$ = new FloatOptions(); - $$->case_idx_ = CASE0; - } - |field_length { - $$ = new FloatOptions(); - $$->case_idx_ = CASE1; - - $$->field_length_ = $1; - } - |precision { - $$ = new FloatOptions(); - $$->case_idx_ = CASE2; - - $$->precision_ = $1; - } - ; - -precision: - OP_LP iconst OP_COMMA iconst OP_RP { - $$ = new Precision(); - $$->case_idx_ = CASE0; - - $$->iconst_1_ = $2; - $$->iconst_2_ = $4; - } - ; - -opt_field_length: - { - $$ = new OptFieldLength(); - $$->case_idx_ = CASE0; - } - |field_length { - $$ = new OptFieldLength(); - $$->case_idx_ = CASE1; - - $$->field_length_ = $1; - } - ; - -field_length: - OP_LP iconst OP_RP { - $$ = new FieldLength(); - $$->case_idx_ = CASE0; - - $$->iconst_ = $2; - } - ; - -literal: - NULL { - $$ = new Literal(); - $$->case_idx_ = CASE0; - } - |FALSE { - $$ = new Literal(); - $$->case_idx_ = CASE1; - } - |TRUE { - $$ = new Literal(); - $$->case_idx_ = CASE2; - } - ; - -columnref: - column_name { - $$ = new Columnref(); - $$->case_idx_ = CASE0; - - $$->column_name_ = $1; - } - |table_name OP_DOT column_name { - $$ = new Columnref(); - $$->case_idx_ = CASE1; - - $$->table_name_ = $1; - $$->column_name_ = $3; - } - ; - -comp_op: - OP_EQUAL { - $$ = new CompOp(); - $$->case_idx_ = CASE0; - } - |OP_GREATEREQ { - $$ = new CompOp(); - $$->case_idx_ = CASE1; - } - |OP_GREATERTHAN { - $$ = new CompOp(); - $$->case_idx_ = CASE2; - } - |OP_LESSEQ { - $$ = new CompOp(); - $$->case_idx_ = CASE3; - } - |OP_LESSTHAN { - $$ = new CompOp(); - $$->case_idx_ = CASE4; - } - |OP_NOTEQUAL { - $$ = new CompOp(); - $$->case_idx_ = CASE5; - } - ; - -all_subquery: - ALL subquery { - $$ = new AllSubquery(); - $$->case_idx_ = CASE0; - - $$->subquery_ = $2; - } - |ANY subquery { - $$ = new AllSubquery(); - $$->case_idx_ = CASE1; - - $$->subquery_ = $2; - } - |SOME subquery { - $$ = new AllSubquery(); - $$->case_idx_ = CASE2; - - $$->subquery_ = $2; - } - ; - -in_subquery: - IN subquery { - $$ = new InSubquery(); - $$->case_idx_ = CASE0; - - $$->subquery_ = $2; - } - |NOT IN subquery { - $$ = new InSubquery(); - $$->case_idx_ = CASE1; - - $$->subquery_ = $3; - } - ; - -expr_list: - expr { - $$ = new ExprList(); - $$->case_idx_ = CASE0; - - $$->expr_ = $1; - } - |expr OP_COMMA expr_list { - $$ = new ExprList(); - $$->case_idx_ = CASE1; - - $$->expr_ = $1; - $$->expr_list_ = $3; - } - ; - -iconst: - ICONST { - $$ = new Iconst(); - $$->case_idx_ = CASE0; - - $$->long_val_ = $1; - } - ; - -fconst: - FCONST { - $$ = new Fconst(); - $$->case_idx_ = CASE0; - - $$->float_val_ = $1; - } - ; - -sconst: - SCONST { - $$ = new Sconst(); - $$->case_idx_ = CASE0; - - $$->str_val_ = $1; - free($1); - } - ; - -ident: - IDENT { - $$ = new Ident(); - $$->case_idx_ = CASE0; - - $$->str_val_ = $1; - free($1); - } - ; - -alias: - ident { - $$ = new Alias(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -column_name: - ident { - $$ = new ColumnName(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -window_name: - ident { - $$ = new WindowName(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -table_name: - ident { - $$ = new TableName(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -constraint_name: - ident { - $$ = new ConstraintName(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -index_name: - ident { - $$ = new IndexName(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -view_name: - ident { - $$ = new ViewName(); - $$->case_idx_ = CASE0; - - $$->ident_ = $1; - } - ; - -%% - diff --git a/parser/flex.l b/parser/flex.l deleted file mode 100755 index f81f634..0000000 --- a/parser/flex.l +++ /dev/null @@ -1,339 +0,0 @@ -%{ -#include "bison_parser.h" -#include -#include -#include -#include -#define TOKEN(name) { return SQL_##name; } -static thread_local std::stringstream strbuf; -%} - -%{ - -#define YYLTYPE_IS_DECLARED 1 - -#define YY_USER_ACTION \ - yylloc->first_line = yylloc->last_line; \ - yylloc->first_column = yylloc->last_column; \ - for(int i = 0; yytext[i] != '\0'; i++) { \ - if(yytext[i] == '\n') { \ - yylloc->last_line++; \ - yylloc->last_column = 0; \ - } \ - else { \ - yylloc->last_column++; \ - } \ - } -%} - -%option reentrant -%option bison-bridge -%option never-interactive -%option batch -%option noyywrap -%option nounput -%option warn -%option case-insensitive -%option bison-locations -%option header-file="flex_lexer.h" -%option outfile="flex_lexer.cpp" -%option prefix="ff_" -%s COMMENT -%x singlequotedstring - -%% - -";" TOKEN(OP_SEMI) -FROM TOKEN(FROM) -DELETE TOKEN(DELETE) -QUICK TOKEN(QUICK) -LOW_PRIORITY TOKEN(LOW_PRIORITY) -IGNORE TOKEN(IGNORE) -ALTER TOKEN(ALTER) -TABLE TOKEN(TABLE) -"," TOKEN(OP_COMMA) -ADD TOKEN(ADD) -COLUMN TOKEN(COLUMN) -")" TOKEN(OP_RP) -"(" TOKEN(OP_LP) -CHANGE TOKEN(CHANGE) -MODIFY TOKEN(MODIFY) -DROP TOKEN(DROP) -FOREIGN TOKEN(FOREIGN) -KEY TOKEN(KEY) -PRIMARY TOKEN(PRIMARY) -INDEX TOKEN(INDEX) -CHECK TOKEN(CHECK) -CONSTRAINT TOKEN(CONSTRAINT) -SET TOKEN(SET) -DEFAULT TOKEN(DEFAULT) -RENAME TOKEN(RENAME) -TO TOKEN(TO) -AFTER TOKEN(AFTER) -FIRST TOKEN(FIRST) -ON TOKEN(ON) -IF TOKEN(IF) -EXISTS TOKEN(EXISTS) -VIEW TOKEN(VIEW) -UPDATE TOKEN(UPDATE) -LIMIT TOKEN(LIMIT) -INTO TOKEN(INTO) -INSERT TOKEN(INSERT) -VALUES TOKEN(VALUES) -AS TOKEN(AS) -DUPLICATE TOKEN(DUPLICATE) -"=" TOKEN(OP_EQUAL) -DELAYED TOKEN(DELAYED) -HIGH_PRIORITY TOKEN(HIGH_PRIORITY) -CREATE TOKEN(CREATE) -UNIQUE TOKEN(UNIQUE) -OR TOKEN(OR) -REPLACE TOKEN(REPLACE) -ALGORITHM TOKEN(ALGORITHM) -UNDEFINED TOKEN(UNDEFINED) -MERGE TOKEN(MERGE) -TEMPTABLE TOKEN(TEMPTABLE) -TEMPORARY TOKEN(TEMPORARY) -NOT TOKEN(NOT) -CHAR TOKEN(CHAR) -BINARY TOKEN(BINARY) -VARCHAR TOKEN(VARCHAR) -VARBINARY TOKEN(VARBINARY) -LONG TOKEN(LONG) -TINYBLOB TOKEN(TINYBLOB) -MEDIUMBLOB TOKEN(MEDIUMBLOB) -LONGBLOB TOKEN(LONGBLOB) -BLOB TOKEN(BLOB) -TINYTEXT TOKEN(TINYTEXT) -MEDIUMTEXT TOKEN(MEDIUMTEXT) -LONGTEXT TOKEN(LONGTEXT) -TEXT TOKEN(TEXT) -BOOL TOKEN(BOOL) -BOOLEAN TOKEN(BOOLEAN) -FLOAT TOKEN(FLOAT) -DECIMAL TOKEN(DECIMAL) -NUMERIC TOKEN(NUMERIC) -FIXED TOKEN(FIXED) -REAL TOKEN(REAL) -DOUBLE TOKEN(DOUBLE) -INT TOKEN(INT) -TINYINT TOKEN(TINYINT) -SMALLINT TOKEN(SMALLINT) -MEDIUMINT TOKEN(MEDIUMINT) -BIGINT TOKEN(BIGINT) -SIGNED TOKEN(SIGNED) -UNSIGNED TOKEN(UNSIGNED) -ZEROFILL TOKEN(ZEROFILL) -NULL TOKEN(NULL) -VISIBLE TOKEN(VISIBLE) -INVISIBLE TOKEN(INVISIBLE) -REFERENCES TOKEN(REFERENCES) -CASCADE TOKEN(CASCADE) -NO TOKEN(NO) -ACTION TOKEN(ACTION) -UNION TOKEN(UNION) -EXCEPT TOKEN(EXCEPT) -INTERSECT TOKEN(INTERSECT) -SELECT TOKEN(SELECT) -WINDOW TOKEN(WINDOW) -PARTITION TOKEN(PARTITION) -BY TOKEN(BY) -ORDER TOKEN(ORDER) -ASC TOKEN(ASC) -DESC TOKEN(DESC) -ROWS TOKEN(ROWS) -RANGE TOKEN(RANGE) -UNBOUNDED TOKEN(UNBOUNDED) -PRECEDING TOKEN(PRECEDING) -CURRENT TOKEN(CURRENT) -ROW TOKEN(ROW) -AND TOKEN(AND) -BETWEEN TOKEN(BETWEEN) -FOLLOWING TOKEN(FOLLOWING) -HAVING TOKEN(HAVING) -GROUP TOKEN(GROUP) -WITH TOKEN(WITH) -ROLLUP TOKEN(ROLLUP) -WHERE TOKEN(WHERE) -LATERAL TOKEN(LATERAL) -USING TOKEN(USING) -JOIN TOKEN(JOIN) -INNER TOKEN(INNER) -CROSS TOKEN(CROSS) -STRAIGHT_JOIN TOKEN(STRAIGHT_JOIN) -NATURAL TOKEN(NATURAL) -RIGHT TOKEN(RIGHT) -LEFT TOKEN(LEFT) -OUTER TOKEN(OUTER) -"*" TOKEN(OP_MUL) -"." TOKEN(OP_DOT) -SQL_NO_CACHE TOKEN(SQL_NO_CACHE) -DISTINCT TOKEN(DISTINCT) -SQL_SMALL_RESULT TOKEN(SQL_SMALL_RESULT) -SQL_BIG_RESULT TOKEN(SQL_BIG_RESULT) -SQL_BUFFER_RESULT TOKEN(SQL_BUFFER_RESULT) -SQL_CALC_FOUND_ROWS TOKEN(SQL_CALC_FOUND_ROWS) -ALL TOKEN(ALL) -RECURSIVE TOKEN(RECURSIVE) -XOR TOKEN(XOR) -IS TOKEN(IS) -TRUE TOKEN(TRUE) -FALSE TOKEN(FALSE) -UNKNOWN TOKEN(UNKNOWN) -IN TOKEN(IN) -SOUNDS TOKEN(SOUNDS) -LIKE TOKEN(LIKE) -REGEXP TOKEN(REGEXP) -"|" TOKEN(OP_OR) -"&" TOKEN(OP_AND) -"<<" TOKEN(OP_SHL) -">>" TOKEN(OP_SHR) -"+" TOKEN(OP_ADD) -"-" TOKEN(OP_SUB) -"/" TOKEN(OP_DIVIDE) -"%" TOKEN(OP_MOD) -"^" TOKEN(OP_XOR) -"~" TOKEN(OP_NOT) -ASCII TOKEN(ASCII) -BIN TOKEN(BIN) -BIT_LENGTH TOKEN(BIT_LENGTH) -CHAR_LENGTH TOKEN(CHAR_LENGTH) -LENGTH TOKEN(LENGTH) -LOWER TOKEN(LOWER) -LTRIM TOKEN(LTRIM) -OCT TOKEN(OCT) -ORD TOKEN(ORD) -QUOTE TOKEN(QUOTE) -REVERSE TOKEN(REVERSE) -RTRIM TOKEN(RTRIM) -SPACE TOKEN(SPACE) -TRIM TOKEN(TRIM) -LEADING TOKEN(LEADING) -TRAILING TOKEN(TRAILING) -UNHEX TOKEN(UNHEX) -UPPER TOKEN(UPPER) -FIND_IN_SET TOKEN(FIND_IN_SET) -INSTR TOKEN(INSTR) -LOCATE TOKEN(LOCATE) -REPEAT TOKEN(REPEAT) -SUBSTRING TOKEN(SUBSTRING) -EXPORT_SET TOKEN(EXPORT_SET) -LPAD TOKEN(LPAD) -RPAD TOKEN(RPAD) -SUBSTRING_INDEX TOKEN(SUBSTRING_INDEX) -CONCAT TOKEN(CONCAT) -CONCAT_WS TOKEN(CONCAT_WS) -ELT TOKEN(ELT) -FIELD TOKEN(FIELD) -MAKE_SET TOKEN(MAKE_SET) -PI TOKEN(PI) -RAND TOKEN(RAND) -ABS TOKEN(ABS) -ACOS TOKEN(ACOS) -ASIN TOKEN(ASIN) -ATAN TOKEN(ATAN) -CEILING TOKEN(CEILING) -COS TOKEN(COS) -COT TOKEN(COT) -DEGREES TOKEN(DEGREES) -EXP TOKEN(EXP) -FLOOR TOKEN(FLOOR) -HEX TOKEN(HEX) -LN TOKEN(LN) -RADIANS TOKEN(RADIANS) -ROUND TOKEN(ROUND) -SIGN TOKEN(SIGN) -SIN TOKEN(SIN) -SQRT TOKEN(SQRT) -TAN TOKEN(TAN) -FORMAT TOKEN(FORMAT) -LOG TOKEN(LOG) -MOD TOKEN(MOD) -POW TOKEN(POW) -TRUNCATE TOKEN(TRUNCATE) -CONV TOKEN(CONV) -ROW_NUMBER TOKEN(ROW_NUMBER) -RANK TOKEN(RANK) -DENSE_RANK TOKEN(DENSE_RANK) -CUME_DIST TOKEN(CUME_DIST) -PERCENT_RANK TOKEN(PERCENT_RANK) -NTILE TOKEN(NTILE) -LEAD TOKEN(LEAD) -LAG TOKEN(LAG) -FIRST_VALUE TOKEN(FIRST_VALUE) -LAST_VALUE TOKEN(LAST_VALUE) -NTH_VALUE TOKEN(NTH_VALUE) -RESPECT TOKEN(RESPECT) -NULLS TOKEN(NULLS) -LAST TOKEN(LAST) -AVG TOKEN(AVG) -BIT_AND TOKEN(BIT_AND) -BIT_OR TOKEN(BIT_OR) -BIT_XOR TOKEN(BIT_XOR) -COUNT TOKEN(COUNT) -MIN TOKEN(MIN) -MAX TOKEN(MAX) -SUM TOKEN(SUM) -STD TOKEN(STD) -STDDEV_SAMP TOKEN(STDDEV_SAMP) -VARIANCE TOKEN(VARIANCE) -VAR_SAMP TOKEN(VAR_SAMP) -GROUP_CONCAT TOKEN(GROUP_CONCAT) -SEPARATOR TOKEN(SEPARATOR) -OVER TOKEN(OVER) -IFNULL TOKEN(IFNULL) -NULLIF TOKEN(NULLIF) -END TOKEN(END) -CASE TOKEN(CASE) -THEN TOKEN(THEN) -WHEN TOKEN(WHEN) -ELSE TOKEN(ELSE) -CAST TOKEN(CAST) -CONVERT TOKEN(CONVERT) -NCHAR TOKEN(NCHAR) -">=" TOKEN(OP_GREATEREQ) -">" TOKEN(OP_GREATERTHAN) -"<=" TOKEN(OP_LESSEQ) -"<" TOKEN(OP_LESSTHAN) -"!=" TOKEN(OP_NOTEQUAL) -ANY TOKEN(ANY) -SOME TOKEN(SOME) - --?[0-9]+"."[0-9]* | -"."[0-9]* { - yylval->double_value = atof(yytext); - return SQL_FCONST; -} - --?[0-9]+ { - yylval->long_value = atol(yytext); - return SQL_ICONST; -} - -[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] { - -} - -[-][-].* { - -} - -\'[^\']*\' { - yylval->charp_value = strdup(yytext); - return SQL_SCONST; -} - -[A-Za-z$][A-Za-z0-9_]*[$]? { - yylval->charp_value = strdup(yytext); - return SQL_IDENT; -} - -[ \t\n]+ { - -} - -. { - return 0; -} - -%% diff --git a/parser/parser_typedef.h b/parser/parser_typedef.h deleted file mode 100755 index ada28ec..0000000 --- a/parser/parser_typedef.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __PARSER_TYPEDEF_H__ -#define __PARSER_TYPEDEF_H__ - -#include - - -#ifndef YYtypeDEF_YY_SCANNER_T -#define YYtypeDEF_YY_SCANNER_T -typedef void* yyscan_t; -#endif - - -#define YYSTYPE FF_STYPE -#define YYLTYPE FF_LTYPE - - -struct FF_CUST_LTYPE { - int first_line; - int first_column; - int last_line; - int last_column; - - int total_column; - - // Length of the string in the SQL query string - int string_length; - - // Parameters. - // int param_id; - std::vector param_list; -}; - -#define FF_LTYPE FF_CUST_LTYPE -#define FF_LTYPE_IS_DECLARED 1 - -#define YY_USER_ACTION \ - yylloc->first_line = yylloc->last_line; \ - yylloc->first_column = yylloc->last_column; \ - for(int i = 0; yytext[i] != '\0'; i++) { \ - yylloc->total_column++; \ - yylloc->string_length++; \ - if(yytext[i] == '\n') { \ - yylloc->last_line++; \ - yylloc->last_column = 0; \ - } \ - else { \ - yylloc->last_column++; \ - } \ - } - -#endif \ No newline at end of file -- Gitee From 1fffa2213265fb2883a6b00ac9cc4cfe13252820 Mon Sep 17 00:00:00 2001 From: PengJiaScu Date: Thu, 16 Nov 2023 07:59:14 +0000 Subject: [PATCH 6/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20src?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ast.cpp | 5546 ------------------------------------------- src/connector.cpp | 177 -- src/instantiate.cpp | 3555 --------------------------- src/mutate.cpp | 1359 ----------- src/tool.cpp | 1122 --------- 5 files changed, 11759 deletions(-) delete mode 100755 src/ast.cpp delete mode 100755 src/connector.cpp delete mode 100755 src/instantiate.cpp delete mode 100755 src/mutate.cpp delete mode 100755 src/tool.cpp diff --git a/src/ast.cpp b/src/ast.cpp deleted file mode 100755 index 9bdb0c8..0000000 --- a/src/ast.cpp +++ /dev/null @@ -1,5546 +0,0 @@ -#include "../include/ast.h" -#include "../include/define.h" -#include - -using namespace std; - -//TRIM**SUBSTRING**BIT_AND**BIT_OR**BIT_XOR**COUNT**MIN**MAX**SUM**STD**STDDEV_SAMP**VARIANCE**VAR_SAMP**GROUP_CONCAT** - -const char* convertToTerminal[] = { - ";", - "FROM", - "DELETE", - "", - "QUICK", - "LOW_PRIORITY", - "IGNORE", - "ALTER TABLE", - ",", - "ADD COLUMN", - ")", - "ADD COLUMN (", - "ADD", - "CHANGE COLUMN", - "MODIFY COLUMN", - "DROP COLUMN", - "DROP FOREIGN KEY", - "DROP PRIMARY KEY", - "DROP INDEX", - "DROP CHECK", - "DROP CONSTRAINT", - "SET DEFAULT (", - "ALTER COLUMN", - "DROP DEFAULT", - "SET", - "ALTER INDEX", - "RENAME TO", - "TO", - "RENAME INDEX", - "RENAME COLUMN", - "AFTER", - "FIRST", - "ON", - "DROP TABLE", - "IF EXISTS", - "DROP VIEW", - "UPDATE", - "LIMIT", - "INTO", - "INSERT", - "(", - "VALUES", - ") VALUES", - "DEFAULT", - "AS", - "ON DUPLICATE KEY UPDATE", - "=", - "DELAYED", - "HIGH_PRIORITY", - "INDEX", - "CREATE", - "UNIQUE", - "VIEW", - "OR REPLACE", - "ALGORITHM = UNDEFINED", - "ALGORITHM = MERGE", - "ALGORITHM = TEMPTABLE", - "TABLE", - "TEMPORARY", - "IF NOT EXISTS", - "REPLACE", - "CHAR", - "BINARY", - "VARCHAR", - "VARBINARY", - "LONG VARBINARY", - "TINYBLOB", - "MEDIUMBLOB", - "LONGBLOB", - "BLOB", - "TINYTEXT", - "MEDIUMTEXT", - "LONGTEXT", - "TEXT", - "BOOL", - "BOOLEAN", - "FLOAT", - "DECIMAL", - "NUMERIC", - "FIXED", - "REAL", - "DOUBLE", - "INT", - "TINYINT", - "SMALLINT", - "MEDIUMINT", - "BIGINT", - "SIGNED", - "UNSIGNED", - "ZEROFILL", - "DEFAULT (", - "NOT NULL", - "VISIBLE", - "INVISIBLE", - "CONSTRAINT", - "CHECK (", - "FOREIGN KEY", - "REFERENCES", - "ON UPDATE", - "ON DELETE", - "CASCADE", - "SET NULL", - "NO ACTION", - "SET DEFAULT", - "PRIMARY KEY", - "UNION", - "EXCEPT", - "INTERSECT", - "SELECT", - "WINDOW", - "PARTITION BY", - "ORDER BY", - "ASC", - "DESC", - "ROWS", - "RANGE", - "UNBOUNDED PRECEDING", - "PRECEDING", - "CURRENT ROW", - "AND", - "BETWEEN", - "UNBOUNDED FOLLOWING", - "FOLLOWING", - "HAVING", - "GROUP BY", - "WITH ROLLUP", - "WHERE", - "LATERAL", - "USING (", - "JOIN", - "INNER JOIN", - "CROSS JOIN", - "STRAIGHT_JOIN", - "NATURAL", - "NATURAL RIGHT", - "NATURAL LEFT", - "INNER", - "OUTER", - "LEFT", - "RIGHT", - "*", - ". *", - "SQL_NO_CACHE", - "DISTINCT", - "SQL_SMALL_RESULT", - "SQL_BIG_RESULT", - "SQL_BUFFER_RESULT", - "SQL_CALC_FOUND_ROWS", - "ALL", - "WITH", - "WITH RECURSIVE", - "OR", - "XOR", - "NOT", - "IS TRUE", - "IS NOT TRUE", - "IS FALSE", - "IS NOT FALSE", - "IS UNKNOWN", - "IS NOT UNKNOWN", - "IS NULL", - "IS NOT NULL", - "IN (", - "NOT IN (", - "NOT BETWEEN", - "SOUNDS LIKE", - "LIKE", - "NOT LIKE", - "REGEXP", - "NOT REGEXP", - "|", - "&", - "<<", - ">>", - "+", - "-", - "/", - "%", - "^", - "~", - "EXISTS", - "ASCII (", - "BIN (", - "BIT_LENGTH (", - "CHAR_LENGTH (", - "LENGTH (", - "LOWER (", - "LTRIM (", - "OCT (", - "ORD (", - "QUOTE (", - "REVERSE (", - "RTRIM (", - "SPACE (", - "TRIM(", - "TRIM( LEADING FROM", - "TRIM( TRAILING FROM", - "UNHEX (", - "UPPER (", - "FIND_IN_SET (", - "INSTR (", - "LEFT (", - "LOCATE (", - "REPEAT (", - "RIGHT (", - "SUBSTRING(", - "TRIM( LEADING", - "TRIM( TRAILING", - "EXPORT_SET (", - "LPAD (", - "REPLACE (", - "RPAD (", - "SUBSTRING_INDEX (", - "INSERT (", - "CHAR (", - "CONCAT (", - "CONCAT_WS (", - "ELT (", - "FIELD (", - "MAKE_SET (", - "PI ( )", - "RAND ( )", - "ABS (", - "ACOS (", - "ASIN (", - "ATAN (", - "CEILING (", - "COS (", - "COT (", - "DEGREES (", - "EXP (", - "FLOOR (", - "HEX (", - "LN (", - "RADIANS (", - "RAND (", - "ROUND (", - "SIGN (", - "SIN (", - "SQRT (", - "TAN (", - "FORMAT (", - "LOG (", - "MOD (", - "POW (", - "TRUNCATE (", - "CONV (", - "ROW_NUMBER ( )", - "RANK ( )", - "DENSE_RANK ( )", - "CUME_DIST ( )", - "PERCENT_RANK ( )", - "NTILE (", - "LEAD (", - "LAG (", - "FIRST_VALUE (", - "LAST_VALUE (", - "NTH_VALUE (", - "RESPECT NULLS", - "IGNORE NULLS", - "FROM FIRST", - "FROM LAST", - "AVG (", - "BIT_AND(", - "BIT_OR(", - "BIT_XOR(", - "COUNT( * )", - "COUNT(", - "COUNT( DISTINCT", - "MIN(", - "MAX(", - "SUM(", - "STD(", - "STDDEV_SAMP(", - "VARIANCE(", - "VAR_SAMP(", - "GROUP_CONCAT(", - "SEPARATOR", - "OVER", - "IF (", - "IFNULL (", - "NULLIF (", - "END", - "CASE", - "THEN", - "WHEN", - "ELSE", - "CAST (", - "CONVERT (", - "NCHAR", - "NULL", - "FALSE", - "TRUE", - ".", - ">=", - ">", - "<=", - "<", - "!=", - "ANY", - "SOME", - "IN", - "NOT IN", - "ICONST", - "FCONST", - "SCONST", - "IDENT", -}; - -void deep_delete(IR * root){ - if (!root) - return; - - if(root->left_) deep_delete(root->left_); - if(root->right_) deep_delete(root->right_); - - if(root->op_) delete root->op_; - - delete root; -} - -IR* deep_copy(const IR* root) { - IR* left = NULL, * right = NULL, * copy_res; - - if (root == nullptr) return nullptr; - - if (root->left_) left = deep_copy(root->left_); - if (root->right_) right = deep_copy(root->right_); - - copy_res = new IR(root, left, right); - - return copy_res; -} - -string IR::to_string(){ - auto res = to_string_core(); - trim_string(res); - return res; -} - -string IR::to_string_core(){ - switch (type_) { - case kIconst: - return std::to_string(long_val_) + " "; - case kFconst: - return std::to_string(float_val_) + " "; - case kSconst: - return str_val_ + " "; - case kIdent: - return str_val_ + " "; - } - - string res; - - if (op_->prefix_ != tEmpty) - res += string(convertToTerminal[op_->prefix_]) + " "; - if (left_ != NULL) - res += left_->to_string_core(); - if (op_->middle_ != tEmpty) - res += string(convertToTerminal[op_->middle_]) + " "; - if (right_ != NULL) - res += right_->to_string_core(); - if (op_->suffix_ != tEmpty) - res += string(convertToTerminal[op_->suffix_]) + " "; - - return res; -} - -void IR::trim_string(string& res) { - char preChar = 0; - int count = 0; - - for (int i = 0; i < res.size(); i++) { - if ((res[i] == ' ') && (preChar == ';')) - res[i] = '\n'; - - preChar = res[i]; - } - - return; -} - -IR* ParseToplevel::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(stmtmulti_); - res = new IR(IRTYPE::kParseToplevel, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void ParseToplevel::deep_delete() { - SAFEDELETE(stmtmulti_); - delete this; -} - -IR* Stmtmulti::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(stmt_); - auto tmp2 = SAFETRANSLATE(stmtmulti_); - res = new IR(IRTYPE::kStmtmulti, OP3(TERMINAL::tEmpty, TERMINAL::tOpSemi, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(stmt_); - res = new IR(IRTYPE::kStmtmulti, OP3(TERMINAL::tEmpty, TERMINAL::tOpSemi, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Stmtmulti::deep_delete() { - SAFEDELETE(stmtmulti_); - SAFEDELETE(stmt_); - delete this; -} - -IR* Stmt::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(create_table_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(create_view_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(create_index_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(select_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(drop_index_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(drop_table_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(drop_view_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(delete_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(update_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(insert_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(alter_table_stmt_); - res = new IR(IRTYPE::kStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Stmt::deep_delete() { - SAFEDELETE(create_table_stmt_); - SAFEDELETE(create_view_stmt_); - SAFEDELETE(create_index_stmt_); - SAFEDELETE(select_stmt_); - SAFEDELETE(drop_index_stmt_); - SAFEDELETE(drop_table_stmt_); - SAFEDELETE(drop_view_stmt_); - SAFEDELETE(delete_stmt_); - SAFEDELETE(update_stmt_); - SAFEDELETE(insert_stmt_); - SAFEDELETE(alter_table_stmt_); - delete this; -} - -IR* DeleteStmt::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_with_clause_); - auto tmp2 = SAFETRANSLATE(opt_delete_options_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(opt_alias_); - auto tmp5 = SAFETRANSLATE(opt_where_clause_); - auto tmp6 = SAFETRANSLATE(opt_order_clause_); - auto tmp7 = SAFETRANSLATE(opt_simple_limit_); - auto tmp8 = new IR(IRTYPE::kDeleteStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp6, tmp7); - auto tmp9 = new IR(IRTYPE::kDeleteStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp8); - auto tmp10 = new IR(IRTYPE::kDeleteStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp9); - auto tmp11 = new IR(IRTYPE::kDeleteStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp10); - auto tmp12 = new IR(IRTYPE::kDeleteStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tFrom, TERMINAL::tEmpty), tmp2, tmp11); - res = new IR(IRTYPE::kDeleteStmt, OP3(TERMINAL::tEmpty, TERMINAL::tDelete, TERMINAL::tEmpty), tmp1, tmp12); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_with_clause_); - auto tmp2 = SAFETRANSLATE(opt_delete_options_); - auto tmp3 = SAFETRANSLATE(table_list_); - auto tmp4 = SAFETRANSLATE(table_reference_list_); - auto tmp5 = SAFETRANSLATE(opt_where_clause_); - auto tmp6 = new IR(IRTYPE::kDeleteStmtTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kDeleteStmtTmp7, OP3(TERMINAL::tEmpty, TERMINAL::tFrom, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kDeleteStmtTmp8, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kDeleteStmt, OP3(TERMINAL::tEmpty, TERMINAL::tDelete, TERMINAL::tEmpty), tmp1, tmp8); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void DeleteStmt::deep_delete() { - SAFEDELETE(opt_simple_limit_); - SAFEDELETE(opt_order_clause_); - SAFEDELETE(opt_where_clause_); - SAFEDELETE(opt_alias_); - SAFEDELETE(table_name_); - SAFEDELETE(opt_delete_options_); - SAFEDELETE(opt_with_clause_); - SAFEDELETE(table_reference_list_); - SAFEDELETE(table_list_); - delete this; -} - -IR* OptDeleteOptions::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(delete_options_); - res = new IR(IRTYPE::kOptDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptDeleteOptions::deep_delete() { - SAFEDELETE(delete_options_); - delete this; -} - -IR* DeleteOptions::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(delete_option_); - res = new IR(IRTYPE::kDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(delete_option_); - auto tmp2 = SAFETRANSLATE(delete_options_); - res = new IR(IRTYPE::kDeleteOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void DeleteOptions::deep_delete() { - SAFEDELETE(delete_option_); - SAFEDELETE(delete_options_); - delete this; -} - -IR* DeleteOption::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kDeleteOption, OP3(TERMINAL::tQuick, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kDeleteOption, OP3(TERMINAL::tLowPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kDeleteOption, OP3(TERMINAL::tIgnore, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void DeleteOption::deep_delete() { - delete this; -} - -IR* AlterTableStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(alter_list_); - res = new IR(IRTYPE::kAlterTableStmt, OP3(TERMINAL::tAlterTable, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void AlterTableStmt::deep_delete() { - SAFEDELETE(alter_list_); - SAFEDELETE(table_name_); - delete this; -} - -IR* AlterList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(alter_list_item_); - res = new IR(IRTYPE::kAlterList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(alter_list_item_); - auto tmp2 = SAFETRANSLATE(alter_list_); - res = new IR(IRTYPE::kAlterList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void AlterList::deep_delete() { - SAFEDELETE(alter_list_item_); - SAFEDELETE(alter_list_); - delete this; -} - -IR* AlterListItem::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(column_name_1_); - auto tmp2 = SAFETRANSLATE(field_def_); - auto tmp3 = SAFETRANSLATE(opt_place_); - auto tmp4 = new IR(IRTYPE::kAlterListItemTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAddColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_element_list_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAddColumnOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(table_constraint_def_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAdd, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(column_name_1_); - auto tmp2 = SAFETRANSLATE(column_name_2_); - auto tmp3 = SAFETRANSLATE(field_def_); - auto tmp4 = SAFETRANSLATE(opt_place_); - auto tmp5 = new IR(IRTYPE::kAlterListItemTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kAlterListItemTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tChangeColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(column_name_1_); - auto tmp2 = SAFETRANSLATE(field_def_); - auto tmp3 = SAFETRANSLATE(opt_place_); - auto tmp4 = new IR(IRTYPE::kAlterListItemTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tModifyColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(column_name_1_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropColumn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(constraint_name_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropForeignKey, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(7) - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropPrimaryKey, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(index_name_1_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropIndex, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(constraint_name_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropCheck, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(constraint_name_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tDropConstraint, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(11) - auto tmp1 = SAFETRANSLATE(column_name_1_); - auto tmp2 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterColumn, TERMINAL::tSetDefaultOpLp, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(12) - auto tmp1 = SAFETRANSLATE(column_name_1_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterColumn, TERMINAL::tDropDefault, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(13) - auto tmp1 = SAFETRANSLATE(column_name_1_); - auto tmp2 = SAFETRANSLATE(visibility_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterColumn, TERMINAL::tSet, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(14) - auto tmp1 = SAFETRANSLATE(index_name_1_); - auto tmp2 = SAFETRANSLATE(visibility_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tAlterIndex, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(15) - auto tmp1 = SAFETRANSLATE(table_name_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tRenameTo, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(16) - auto tmp1 = SAFETRANSLATE(index_name_1_); - auto tmp2 = SAFETRANSLATE(index_name_2_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tRenameIndex, TERMINAL::tTo, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(17) - auto tmp1 = SAFETRANSLATE(column_name_1_); - auto tmp2 = SAFETRANSLATE(column_name_2_); - res = new IR(IRTYPE::kAlterListItem, OP3(TERMINAL::tRenameColumn, TERMINAL::tTo, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void AlterListItem::deep_delete() { - SAFEDELETE(opt_place_); - SAFEDELETE(field_def_); - SAFEDELETE(column_name_1_); - SAFEDELETE(column_name_2_); - SAFEDELETE(table_element_list_); - SAFEDELETE(table_constraint_def_); - SAFEDELETE(constraint_name_); - SAFEDELETE(index_name_1_); - SAFEDELETE(index_name_2_); - SAFEDELETE(expr_root_); - SAFEDELETE(visibility_); - SAFEDELETE(table_name_); - delete this; -} - -IR* OptPlace::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptPlace, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_name_); - res = new IR(IRTYPE::kOptPlace, OP3(TERMINAL::tAfter, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOptPlace, OP3(TERMINAL::tFirst, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptPlace::deep_delete() { - SAFEDELETE(column_name_); - delete this; -} - -IR* DropIndexStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(index_name_); - auto tmp2 = SAFETRANSLATE(table_name_); - res = new IR(IRTYPE::kDropIndexStmt, OP3(TERMINAL::tDropIndex, TERMINAL::tOn, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void DropIndexStmt::deep_delete() { - SAFEDELETE(table_name_); - SAFEDELETE(index_name_); - delete this; -} - -IR* DropTableStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(if_exists_); - auto tmp2 = SAFETRANSLATE(table_list_); - res = new IR(IRTYPE::kDropTableStmt, OP3(TERMINAL::tDropTable, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void DropTableStmt::deep_delete() { - SAFEDELETE(table_list_); - SAFEDELETE(if_exists_); - delete this; -} - -IR* IfExists::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kIfExists, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kIfExists, OP3(TERMINAL::tIfExists, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void IfExists::deep_delete() { - delete this; -} - -IR* TableList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(table_name_); - res = new IR(IRTYPE::kTableList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(table_list_); - res = new IR(IRTYPE::kTableList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableList::deep_delete() { - SAFEDELETE(table_name_); - SAFEDELETE(table_list_); - delete this; -} - -IR* DropViewStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(if_exists_); - auto tmp2 = SAFETRANSLATE(table_list_); - res = new IR(IRTYPE::kDropViewStmt, OP3(TERMINAL::tDropView, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void DropViewStmt::deep_delete() { - SAFEDELETE(table_list_); - SAFEDELETE(if_exists_); - delete this; -} - -IR* UpdateStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_with_clause_); - auto tmp2 = SAFETRANSLATE(opt_low_priority_); - auto tmp3 = SAFETRANSLATE(opt_ignore_); - auto tmp4 = SAFETRANSLATE(table_reference_list_); - auto tmp5 = SAFETRANSLATE(update_list_); - auto tmp6 = SAFETRANSLATE(opt_where_clause_); - auto tmp7 = SAFETRANSLATE(opt_order_clause_); - auto tmp8 = SAFETRANSLATE(opt_simple_limit_); - auto tmp9 = new IR(IRTYPE::kUpdateStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp7, tmp8); - auto tmp10 = new IR(IRTYPE::kUpdateStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp6, tmp9); - auto tmp11 = new IR(IRTYPE::kUpdateStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp10); - auto tmp12 = new IR(IRTYPE::kUpdateStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tSet, TERMINAL::tEmpty), tmp4, tmp11); - auto tmp13 = new IR(IRTYPE::kUpdateStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp12); - auto tmp14 = new IR(IRTYPE::kUpdateStmtTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp13); - res = new IR(IRTYPE::kUpdateStmt, OP3(TERMINAL::tEmpty, TERMINAL::tUpdate, TERMINAL::tEmpty), tmp1, tmp14); - - TRANSLATEEND -} - -void UpdateStmt::deep_delete() { - SAFEDELETE(opt_simple_limit_); - SAFEDELETE(opt_order_clause_); - SAFEDELETE(opt_where_clause_); - SAFEDELETE(update_list_); - SAFEDELETE(table_reference_list_); - SAFEDELETE(opt_ignore_); - SAFEDELETE(opt_low_priority_); - SAFEDELETE(opt_with_clause_); - delete this; -} - -IR* OptSimpleLimit::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptSimpleLimit, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(iconst_); - res = new IR(IRTYPE::kOptSimpleLimit, OP3(TERMINAL::tLimit, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptSimpleLimit::deep_delete() { - SAFEDELETE(iconst_); - delete this; -} - -IR* OptWithClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptWithClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(with_clause_); - res = new IR(IRTYPE::kOptWithClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptWithClause::deep_delete() { - SAFEDELETE(with_clause_); - delete this; -} - -IR* OptLowPriority::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptLowPriority, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptLowPriority, OP3(TERMINAL::tLowPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptLowPriority::deep_delete() { - delete this; -} - -IR* InsertStmt::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(insert_lock_option_); - auto tmp2 = SAFETRANSLATE(opt_ignore_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(insert_from_constructor_); - auto tmp5 = SAFETRANSLATE(opt_values_reference_); - auto tmp6 = SAFETRANSLATE(opt_insert_update_list_); - auto tmp7 = new IR(IRTYPE::kInsertStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp6); - auto tmp8 = new IR(IRTYPE::kInsertStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp7); - auto tmp9 = new IR(IRTYPE::kInsertStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp8); - auto tmp10 = new IR(IRTYPE::kInsertStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tInto, TERMINAL::tEmpty), tmp2, tmp9); - res = new IR(IRTYPE::kInsertStmt, OP3(TERMINAL::tInsert, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp10); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(insert_lock_option_); - auto tmp2 = SAFETRANSLATE(opt_ignore_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(update_list_); - auto tmp5 = SAFETRANSLATE(opt_values_reference_); - auto tmp6 = SAFETRANSLATE(opt_insert_update_list_); - auto tmp7 = new IR(IRTYPE::kInsertStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp6); - auto tmp8 = new IR(IRTYPE::kInsertStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp7); - auto tmp9 = new IR(IRTYPE::kInsertStmtTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tSet, TERMINAL::tEmpty), tmp3, tmp8); - auto tmp10 = new IR(IRTYPE::kInsertStmtTmp7, OP3(TERMINAL::tEmpty, TERMINAL::tInto, TERMINAL::tEmpty), tmp2, tmp9); - res = new IR(IRTYPE::kInsertStmt, OP3(TERMINAL::tInsert, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp10); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(insert_lock_option_); - auto tmp2 = SAFETRANSLATE(opt_ignore_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(insert_query_expression_); - auto tmp5 = SAFETRANSLATE(opt_insert_update_list_); - auto tmp6 = new IR(IRTYPE::kInsertStmtTmp8, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kInsertStmtTmp9, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kInsertStmtTmp10, OP3(TERMINAL::tEmpty, TERMINAL::tInto, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kInsertStmt, OP3(TERMINAL::tInsert, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp8); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void InsertStmt::deep_delete() { - SAFEDELETE(opt_insert_update_list_); - SAFEDELETE(opt_values_reference_); - SAFEDELETE(insert_from_constructor_); - SAFEDELETE(table_name_); - SAFEDELETE(opt_ignore_); - SAFEDELETE(insert_lock_option_); - SAFEDELETE(update_list_); - SAFEDELETE(insert_query_expression_); - delete this; -} - -IR* InsertQueryExpression::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(query_expression_); - res = new IR(IRTYPE::kInsertQueryExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_list_); - auto tmp2 = SAFETRANSLATE(query_expression_); - res = new IR(IRTYPE::kInsertQueryExpression, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void InsertQueryExpression::deep_delete() { - SAFEDELETE(query_expression_); - SAFEDELETE(column_list_); - delete this; -} - -IR* InsertFromConstructor::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(values_list_); - res = new IR(IRTYPE::kInsertFromConstructor, OP3(TERMINAL::tValues, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_list_); - auto tmp2 = SAFETRANSLATE(values_list_); - res = new IR(IRTYPE::kInsertFromConstructor, OP3(TERMINAL::tOpLp, TERMINAL::tOpRpValues, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void InsertFromConstructor::deep_delete() { - SAFEDELETE(values_list_); - SAFEDELETE(column_list_); - delete this; -} - -IR* ValuesList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(row_value_); - res = new IR(IRTYPE::kValuesList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(row_value_); - auto tmp2 = SAFETRANSLATE(values_list_); - res = new IR(IRTYPE::kValuesList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ValuesList::deep_delete() { - SAFEDELETE(row_value_); - SAFEDELETE(values_list_); - delete this; -} - -IR* RowValue::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_values_); - res = new IR(IRTYPE::kRowValue, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void RowValue::deep_delete() { - SAFEDELETE(opt_values_); - delete this; -} - -IR* OptValues::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptValues, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(values_); - res = new IR(IRTYPE::kOptValues, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptValues::deep_delete() { - SAFEDELETE(values_); - delete this; -} - -IR* Values::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_or_default_); - res = new IR(IRTYPE::kValues, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_or_default_); - auto tmp2 = SAFETRANSLATE(values_); - res = new IR(IRTYPE::kValues, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Values::deep_delete() { - SAFEDELETE(expr_or_default_); - SAFEDELETE(values_); - delete this; -} - -IR* ExprOrDefault::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kExprOrDefault, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kExprOrDefault, OP3(TERMINAL::tDefault, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ExprOrDefault::deep_delete() { - SAFEDELETE(expr_root_); - delete this; -} - -IR* OptValuesReference::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptValuesReference, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(opt_column_list_); - res = new IR(IRTYPE::kOptValuesReference, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptValuesReference::deep_delete() { - SAFEDELETE(opt_column_list_); - SAFEDELETE(table_name_); - delete this; -} - -IR* OptInsertUpdateList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptInsertUpdateList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(update_list_); - res = new IR(IRTYPE::kOptInsertUpdateList, OP3(TERMINAL::tOnDuplicateKeyUpdate, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptInsertUpdateList::deep_delete() { - SAFEDELETE(update_list_); - delete this; -} - -IR* UpdateList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(update_elem_); - res = new IR(IRTYPE::kUpdateList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(update_elem_); - auto tmp2 = SAFETRANSLATE(update_list_); - res = new IR(IRTYPE::kUpdateList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void UpdateList::deep_delete() { - SAFEDELETE(update_elem_); - SAFEDELETE(update_list_); - delete this; -} - -IR* UpdateElem::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(columnref_); - auto tmp2 = SAFETRANSLATE(expr_or_default_); - res = new IR(IRTYPE::kUpdateElem, OP3(TERMINAL::tEmpty, TERMINAL::tOpEqual, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void UpdateElem::deep_delete() { - SAFEDELETE(expr_or_default_); - SAFEDELETE(columnref_); - delete this; -} - -IR* InsertLockOption::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tLowPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tDelayed, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kInsertLockOption, OP3(TERMINAL::tHighPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void InsertLockOption::deep_delete() { - delete this; -} - -IR* OptIgnore::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptIgnore, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptIgnore, OP3(TERMINAL::tIgnore, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptIgnore::deep_delete() { - delete this; -} - -IR* CreateIndexStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_unique_); - auto tmp2 = SAFETRANSLATE(index_name_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(key_list_with_expression_); - auto tmp5 = new IR(IRTYPE::kCreateIndexStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tOpRp), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kCreateIndexStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOn, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kCreateIndexStmt, OP3(TERMINAL::tCreate, TERMINAL::tIndex, TERMINAL::tEmpty), tmp1, tmp6); - - TRANSLATEEND -} - -void CreateIndexStmt::deep_delete() { - SAFEDELETE(key_list_with_expression_); - SAFEDELETE(table_name_); - SAFEDELETE(index_name_); - SAFEDELETE(opt_unique_); - delete this; -} - -IR* OptUnique::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptUnique, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptUnique, OP3(TERMINAL::tUnique, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptUnique::deep_delete() { - delete this; -} - -IR* CreateViewStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_or_replace_); - auto tmp2 = SAFETRANSLATE(opt_view_algorithm_); - auto tmp3 = SAFETRANSLATE(view_name_); - auto tmp4 = SAFETRANSLATE(opt_column_list_); - auto tmp5 = SAFETRANSLATE(query_expression_); - auto tmp6 = new IR(IRTYPE::kCreateViewStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kCreateViewStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kCreateViewStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tView, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kCreateViewStmt, OP3(TERMINAL::tCreate, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp8); - - TRANSLATEEND -} - -void CreateViewStmt::deep_delete() { - SAFEDELETE(query_expression_); - SAFEDELETE(opt_column_list_); - SAFEDELETE(view_name_); - SAFEDELETE(opt_view_algorithm_); - SAFEDELETE(opt_or_replace_); - delete this; -} - -IR* OptOrReplace::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptOrReplace, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptOrReplace, OP3(TERMINAL::tOrReplace, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptOrReplace::deep_delete() { - delete this; -} - -IR* OptViewAlgorithm::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tAlgorithmOpEqualUndefined, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tAlgorithmOpEqualMerge, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kOptViewAlgorithm, OP3(TERMINAL::tAlgorithmOpEqualTemptable, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptViewAlgorithm::deep_delete() { - delete this; -} - -IR* CreateTableStmt::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_temporary_); - auto tmp2 = SAFETRANSLATE(opt_if_not_exists_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(table_element_list_); - auto tmp5 = SAFETRANSLATE(opt_duplicate_as_qe_); - auto tmp6 = new IR(IRTYPE::kCreateTableStmtTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kCreateTableStmtTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kCreateTableStmtTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kCreateTableStmt, OP3(TERMINAL::tCreate, TERMINAL::tTable, TERMINAL::tEmpty), tmp1, tmp8); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_temporary_); - auto tmp2 = SAFETRANSLATE(opt_if_not_exists_); - auto tmp3 = SAFETRANSLATE(table_name_); - auto tmp4 = SAFETRANSLATE(duplicate_as_qe_); - auto tmp5 = new IR(IRTYPE::kCreateTableStmtTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kCreateTableStmtTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kCreateTableStmt, OP3(TERMINAL::tCreate, TERMINAL::tTable, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void CreateTableStmt::deep_delete() { - SAFEDELETE(opt_duplicate_as_qe_); - SAFEDELETE(table_element_list_); - SAFEDELETE(table_name_); - SAFEDELETE(opt_if_not_exists_); - SAFEDELETE(opt_temporary_); - SAFEDELETE(duplicate_as_qe_); - delete this; -} - -IR* OptTemporary::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptTemporary, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptTemporary, OP3(TERMINAL::tTemporary, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptTemporary::deep_delete() { - delete this; -} - -IR* OptIfNotExists::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptIfNotExists, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptIfNotExists, OP3(TERMINAL::tIfNotExists, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptIfNotExists::deep_delete() { - delete this; -} - -IR* OptDuplicateAsQe::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptDuplicateAsQe, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(duplicate_as_qe_); - res = new IR(IRTYPE::kOptDuplicateAsQe, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptDuplicateAsQe::deep_delete() { - SAFEDELETE(duplicate_as_qe_); - delete this; -} - -IR* DuplicateAsQe::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(duplicate_); - auto tmp2 = SAFETRANSLATE(query_expression_); - res = new IR(IRTYPE::kDuplicateAsQe, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(query_expression_); - res = new IR(IRTYPE::kDuplicateAsQe, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void DuplicateAsQe::deep_delete() { - SAFEDELETE(query_expression_); - SAFEDELETE(duplicate_); - delete this; -} - -IR* Duplicate::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kDuplicate, OP3(TERMINAL::tReplace, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kDuplicate, OP3(TERMINAL::tIgnore, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Duplicate::deep_delete() { - delete this; -} - -IR* TableElementList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(table_element_); - res = new IR(IRTYPE::kTableElementList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_element_); - auto tmp2 = SAFETRANSLATE(table_element_list_); - res = new IR(IRTYPE::kTableElementList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableElementList::deep_delete() { - SAFEDELETE(table_element_); - SAFEDELETE(table_element_list_); - delete this; -} - -IR* TableElement::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(column_def_); - res = new IR(IRTYPE::kTableElement, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_constraint_def_); - res = new IR(IRTYPE::kTableElement, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableElement::deep_delete() { - SAFEDELETE(column_def_); - SAFEDELETE(table_constraint_def_); - delete this; -} - -IR* ColumnDef::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(column_name_); - auto tmp2 = SAFETRANSLATE(field_def_); - res = new IR(IRTYPE::kColumnDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void ColumnDef::deep_delete() { - SAFEDELETE(field_def_); - SAFEDELETE(column_name_); - delete this; -} - -IR* FieldDef::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(data_type_); - auto tmp2 = SAFETRANSLATE(opt_column_attribute_list_); - res = new IR(IRTYPE::kFieldDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void FieldDef::deep_delete() { - SAFEDELETE(opt_column_attribute_list_); - SAFEDELETE(data_type_); - delete this; -} - -IR* DataType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(number_type_); - res = new IR(IRTYPE::kDataType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(bool_type_); - res = new IR(IRTYPE::kDataType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(string_type_); - res = new IR(IRTYPE::kDataType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void DataType::deep_delete() { - SAFEDELETE(number_type_); - SAFEDELETE(bool_type_); - SAFEDELETE(string_type_); - delete this; -} - -IR* StringType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tChar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tBinary, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(field_length_); - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tVarchar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(field_length_); - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tVarbinary, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tLongVarbinary, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(5) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tTinyblob, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(6) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tMediumblob, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(7) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tLongblob, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tBlob, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tTinytext, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(10) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tMediumtext, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(11) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tLongtext, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(12) - res = new IR(IRTYPE::kStringType, OP3(TERMINAL::tText, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void StringType::deep_delete() { - SAFEDELETE(opt_field_length_); - SAFEDELETE(field_length_); - delete this; -} - -IR* BoolType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kBoolType, OP3(TERMINAL::tBool, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kBoolType, OP3(TERMINAL::tBoolean, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void BoolType::deep_delete() { - delete this; -} - -IR* NumberType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(int_type_); - auto tmp2 = SAFETRANSLATE(opt_field_options_); - res = new IR(IRTYPE::kNumberType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(real_type_); - auto tmp2 = SAFETRANSLATE(opt_precision_); - auto tmp3 = SAFETRANSLATE(opt_field_options_); - auto tmp4 = new IR(IRTYPE::kNumberTypeTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kNumberType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(numeric_type_); - auto tmp2 = SAFETRANSLATE(float_options_); - auto tmp3 = SAFETRANSLATE(opt_field_options_); - auto tmp4 = new IR(IRTYPE::kNumberTypeTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kNumberType, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void NumberType::deep_delete() { - SAFEDELETE(opt_field_options_); - SAFEDELETE(int_type_); - SAFEDELETE(opt_precision_); - SAFEDELETE(real_type_); - SAFEDELETE(float_options_); - SAFEDELETE(numeric_type_); - delete this; -} - -IR* NumericType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tFloat, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tDecimal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tNumeric, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kNumericType, OP3(TERMINAL::tFixed, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void NumericType::deep_delete() { - delete this; -} - -IR* RealType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kRealType, OP3(TERMINAL::tReal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kRealType, OP3(TERMINAL::tDouble, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void RealType::deep_delete() { - delete this; -} - -IR* OptPrecision::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptPrecision, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(precision_); - res = new IR(IRTYPE::kOptPrecision, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptPrecision::deep_delete() { - SAFEDELETE(precision_); - delete this; -} - -IR* IntType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tInt, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tTinyint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tSmallint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tMediumint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(4) - res = new IR(IRTYPE::kIntType, OP3(TERMINAL::tBigint, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void IntType::deep_delete() { - delete this; -} - -IR* OptFieldOptions::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptFieldOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(field_option_list_); - res = new IR(IRTYPE::kOptFieldOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptFieldOptions::deep_delete() { - SAFEDELETE(field_option_list_); - delete this; -} - -IR* FieldOptionList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(field_option_); - res = new IR(IRTYPE::kFieldOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(field_option_); - auto tmp2 = SAFETRANSLATE(field_option_list_); - res = new IR(IRTYPE::kFieldOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void FieldOptionList::deep_delete() { - SAFEDELETE(field_option_); - SAFEDELETE(field_option_list_); - delete this; -} - -IR* FieldOption::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kFieldOption, OP3(TERMINAL::tSigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kFieldOption, OP3(TERMINAL::tUnsigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kFieldOption, OP3(TERMINAL::tZerofill, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void FieldOption::deep_delete() { - delete this; -} - -IR* OptColumnAttributeList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_attribute_list_); - res = new IR(IRTYPE::kOptColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptColumnAttributeList::deep_delete() { - SAFEDELETE(column_attribute_list_); - delete this; -} - -IR* ColumnAttributeList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(column_attribute_); - res = new IR(IRTYPE::kColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_attribute_); - auto tmp2 = SAFETRANSLATE(column_attribute_list_); - res = new IR(IRTYPE::kColumnAttributeList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ColumnAttributeList::deep_delete() { - SAFEDELETE(column_attribute_); - SAFEDELETE(column_attribute_list_); - delete this; -} - -IR* ColumnAttribute::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(not_null_); - res = new IR(IRTYPE::kColumnAttribute, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(default_attribute_); - res = new IR(IRTYPE::kColumnAttribute, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(visibility_); - res = new IR(IRTYPE::kColumnAttribute, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ColumnAttribute::deep_delete() { - SAFEDELETE(not_null_); - SAFEDELETE(default_attribute_); - SAFEDELETE(visibility_); - delete this; -} - -IR* DefaultAttribute::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kDefaultAttribute, OP3(TERMINAL::tDefaultOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void DefaultAttribute::deep_delete() { - SAFEDELETE(expr_root_); - delete this; -} - -IR* NotNull::translate() { - TRANSLATESTART - - res = new IR(IRTYPE::kNotNull, OP3(TERMINAL::tNotNull, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - - TRANSLATEEND -} - -void NotNull::deep_delete() { - delete this; -} - -IR* Visibility::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kVisibility, OP3(TERMINAL::tVisible, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kVisibility, OP3(TERMINAL::tInvisible, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Visibility::deep_delete() { - delete this; -} - -IR* OptConstraintName::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptConstraintName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(constraint_name_); - res = new IR(IRTYPE::kOptConstraintName, OP3(TERMINAL::tConstraint, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptConstraintName::deep_delete() { - SAFEDELETE(constraint_name_); - delete this; -} - -IR* CheckConstraint::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kCheckConstraint, OP3(TERMINAL::tCheckOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void CheckConstraint::deep_delete() { - SAFEDELETE(expr_root_); - delete this; -} - -IR* TableConstraintDef::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_index_name_); - auto tmp2 = SAFETRANSLATE(key_list_with_expression_); - res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tIndex, TERMINAL::tOpLp, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_constraint_name_); - auto tmp2 = SAFETRANSLATE(constraint_key_type_); - auto tmp3 = SAFETRANSLATE(opt_index_name_); - auto tmp4 = SAFETRANSLATE(key_list_with_expression_); - auto tmp5 = new IR(IRTYPE::kTableConstraintDefTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tOpRp), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kTableConstraintDefTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(opt_constraint_name_); - auto tmp2 = SAFETRANSLATE(check_constraint_); - res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(opt_constraint_name_); - auto tmp2 = SAFETRANSLATE(opt_index_name_); - auto tmp3 = SAFETRANSLATE(key_list_); - auto tmp4 = SAFETRANSLATE(references_); - auto tmp5 = new IR(IRTYPE::kTableConstraintDefTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kTableConstraintDefTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kTableConstraintDef, OP3(TERMINAL::tEmpty, TERMINAL::tForeignKey, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableConstraintDef::deep_delete() { - SAFEDELETE(key_list_with_expression_); - SAFEDELETE(opt_index_name_); - SAFEDELETE(constraint_key_type_); - SAFEDELETE(opt_constraint_name_); - SAFEDELETE(check_constraint_); - SAFEDELETE(references_); - SAFEDELETE(key_list_); - delete this; -} - -IR* References::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(column_list_); - auto tmp3 = SAFETRANSLATE(opt_on_update_delete_); - auto tmp4 = new IR(IRTYPE::kReferencesTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kReferences, OP3(TERMINAL::tReferences, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp1, tmp4); - - TRANSLATEEND -} - -void References::deep_delete() { - SAFEDELETE(opt_on_update_delete_); - SAFEDELETE(column_list_); - SAFEDELETE(table_name_); - delete this; -} - -IR* OptOnUpdateDelete::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(on_update_option_1_); - res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnUpdate, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(on_update_option_1_); - res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnDelete, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(on_update_option_1_); - auto tmp2 = SAFETRANSLATE(on_update_option_2_); - res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnUpdate, TERMINAL::tOnDelete, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(on_update_option_1_); - auto tmp2 = SAFETRANSLATE(on_update_option_2_); - res = new IR(IRTYPE::kOptOnUpdateDelete, OP3(TERMINAL::tOnDelete, TERMINAL::tOnUpdate, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptOnUpdateDelete::deep_delete() { - SAFEDELETE(on_update_option_1_); - SAFEDELETE(on_update_option_2_); - delete this; -} - -IR* OnUpdateOption::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tCascade, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tSetNull, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tNoAction, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kOnUpdateOption, OP3(TERMINAL::tSetDefault, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OnUpdateOption::deep_delete() { - delete this; -} - -IR* KeyList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(key_part_); - res = new IR(IRTYPE::kKeyList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(key_part_); - auto tmp2 = SAFETRANSLATE(key_list_); - res = new IR(IRTYPE::kKeyList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void KeyList::deep_delete() { - SAFEDELETE(key_part_); - SAFEDELETE(key_list_); - delete this; -} - -IR* KeyListWithExpression::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(key_part_with_expression_); - res = new IR(IRTYPE::kKeyListWithExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(key_part_with_expression_); - auto tmp2 = SAFETRANSLATE(key_list_with_expression_); - res = new IR(IRTYPE::kKeyListWithExpression, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void KeyListWithExpression::deep_delete() { - SAFEDELETE(key_part_with_expression_); - SAFEDELETE(key_list_with_expression_); - delete this; -} - -IR* KeyPartWithExpression::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(key_part_); - res = new IR(IRTYPE::kKeyPartWithExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_root_); - auto tmp2 = SAFETRANSLATE(opt_ordering_direction_); - res = new IR(IRTYPE::kKeyPartWithExpression, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void KeyPartWithExpression::deep_delete() { - SAFEDELETE(key_part_); - SAFEDELETE(opt_ordering_direction_); - SAFEDELETE(expr_root_); - delete this; -} - -IR* KeyPart::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(column_name_); - auto tmp2 = SAFETRANSLATE(opt_ordering_direction_); - res = new IR(IRTYPE::kKeyPart, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_name_); - auto tmp2 = SAFETRANSLATE(iconst_); - auto tmp3 = SAFETRANSLATE(opt_ordering_direction_); - auto tmp4 = new IR(IRTYPE::kKeyPartTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kKeyPart, OP3(TERMINAL::tEmpty, TERMINAL::tOpLp, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void KeyPart::deep_delete() { - SAFEDELETE(opt_ordering_direction_); - SAFEDELETE(column_name_); - SAFEDELETE(iconst_); - delete this; -} - -IR* ConstraintKeyType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kConstraintKeyType, OP3(TERMINAL::tPrimaryKey, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kConstraintKeyType, OP3(TERMINAL::tUnique, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ConstraintKeyType::deep_delete() { - delete this; -} - -IR* OptIndexName::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptIndexName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(index_name_); - res = new IR(IRTYPE::kOptIndexName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptIndexName::deep_delete() { - SAFEDELETE(index_name_); - delete this; -} - -IR* SelectStmt::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(query_expression_); - res = new IR(IRTYPE::kSelectStmt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void SelectStmt::deep_delete() { - SAFEDELETE(query_expression_); - delete this; -} - -IR* QueryExpression::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(query_expression_body_); - auto tmp2 = SAFETRANSLATE(opt_order_clause_); - auto tmp3 = SAFETRANSLATE(opt_limit_clause_); - auto tmp4 = new IR(IRTYPE::kQueryExpressionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kQueryExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(with_clause_); - auto tmp2 = SAFETRANSLATE(query_expression_body_); - auto tmp3 = SAFETRANSLATE(opt_order_clause_); - auto tmp4 = SAFETRANSLATE(opt_limit_clause_); - auto tmp5 = new IR(IRTYPE::kQueryExpressionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kQueryExpressionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kQueryExpression, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void QueryExpression::deep_delete() { - SAFEDELETE(opt_limit_clause_); - SAFEDELETE(opt_order_clause_); - SAFEDELETE(query_expression_body_); - SAFEDELETE(with_clause_); - delete this; -} - -IR* QueryExpressionBody::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(query_primary_); - res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(query_expression_parens_); - res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(query_expression_body_1_); - auto tmp2 = SAFETRANSLATE(opt_union_option_); - auto tmp3 = SAFETRANSLATE(query_expression_body_2_); - auto tmp4 = new IR(IRTYPE::kQueryExpressionBodyTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tUnion, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(query_expression_body_1_); - auto tmp2 = SAFETRANSLATE(opt_union_option_); - auto tmp3 = SAFETRANSLATE(query_expression_body_2_); - auto tmp4 = new IR(IRTYPE::kQueryExpressionBodyTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tExcept, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(query_expression_body_1_); - auto tmp2 = SAFETRANSLATE(opt_union_option_); - auto tmp3 = SAFETRANSLATE(query_expression_body_2_); - auto tmp4 = new IR(IRTYPE::kQueryExpressionBodyTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kQueryExpressionBody, OP3(TERMINAL::tEmpty, TERMINAL::tIntersect, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void QueryExpressionBody::deep_delete() { - SAFEDELETE(query_primary_); - SAFEDELETE(query_expression_parens_); - SAFEDELETE(query_expression_body_1_); - SAFEDELETE(query_expression_body_2_); - SAFEDELETE(opt_union_option_); - delete this; -} - -IR* QueryPrimary::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(query_specification_); - res = new IR(IRTYPE::kQueryPrimary, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void QueryPrimary::deep_delete() { - SAFEDELETE(query_specification_); - delete this; -} - -IR* QuerySpecification::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_select_options_); - auto tmp2 = SAFETRANSLATE(select_item_list_); - auto tmp3 = SAFETRANSLATE(opt_from_clause_); - auto tmp4 = SAFETRANSLATE(opt_where_clause_); - auto tmp5 = SAFETRANSLATE(opt_group_clause_); - auto tmp6 = SAFETRANSLATE(opt_having_clause_); - auto tmp7 = SAFETRANSLATE(opt_window_clause_); - auto tmp8 = new IR(IRTYPE::kQuerySpecificationTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp6, tmp7); - auto tmp9 = new IR(IRTYPE::kQuerySpecificationTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp5, tmp8); - auto tmp10 = new IR(IRTYPE::kQuerySpecificationTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp9); - auto tmp11 = new IR(IRTYPE::kQuerySpecificationTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp10); - auto tmp12 = new IR(IRTYPE::kQuerySpecificationTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp11); - res = new IR(IRTYPE::kQuerySpecification, OP3(TERMINAL::tSelect, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp12); - - TRANSLATEEND -} - -void QuerySpecification::deep_delete() { - SAFEDELETE(opt_window_clause_); - SAFEDELETE(opt_having_clause_); - SAFEDELETE(opt_group_clause_); - SAFEDELETE(opt_where_clause_); - SAFEDELETE(opt_from_clause_); - SAFEDELETE(select_item_list_); - SAFEDELETE(opt_select_options_); - delete this; -} - -IR* OptWindowClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptWindowClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(window_definition_list_); - res = new IR(IRTYPE::kOptWindowClause, OP3(TERMINAL::tWindow, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptWindowClause::deep_delete() { - SAFEDELETE(window_definition_list_); - delete this; -} - -IR* WindowDefinitionList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(window_definition_); - res = new IR(IRTYPE::kWindowDefinitionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(window_definition_); - auto tmp2 = SAFETRANSLATE(window_definition_list_); - res = new IR(IRTYPE::kWindowDefinitionList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowDefinitionList::deep_delete() { - SAFEDELETE(window_definition_); - SAFEDELETE(window_definition_list_); - delete this; -} - -IR* WindowDefinition::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(window_name_); - auto tmp2 = SAFETRANSLATE(window_spec_); - res = new IR(IRTYPE::kWindowDefinition, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void WindowDefinition::deep_delete() { - SAFEDELETE(window_spec_); - SAFEDELETE(window_name_); - delete this; -} - -IR* WindowSpec::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(window_spec_details_); - res = new IR(IRTYPE::kWindowSpec, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void WindowSpec::deep_delete() { - SAFEDELETE(window_spec_details_); - delete this; -} - -IR* WindowSpecDetails::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_existing_window_name_); - auto tmp2 = SAFETRANSLATE(opt_partition_clause_); - auto tmp3 = SAFETRANSLATE(opt_window_order_by_clause_); - auto tmp4 = SAFETRANSLATE(opt_window_frame_clause_); - auto tmp5 = new IR(IRTYPE::kWindowSpecDetailsTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kWindowSpecDetailsTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kWindowSpecDetails, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - - TRANSLATEEND -} - -void WindowSpecDetails::deep_delete() { - SAFEDELETE(opt_window_frame_clause_); - SAFEDELETE(opt_window_order_by_clause_); - SAFEDELETE(opt_partition_clause_); - SAFEDELETE(opt_existing_window_name_); - delete this; -} - -IR* OptExistingWindowName::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptExistingWindowName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(window_name_); - res = new IR(IRTYPE::kOptExistingWindowName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptExistingWindowName::deep_delete() { - SAFEDELETE(window_name_); - delete this; -} - -IR* OptPartitionClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptPartitionClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_root_list_); - res = new IR(IRTYPE::kOptPartitionClause, OP3(TERMINAL::tPartitionBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptPartitionClause::deep_delete() { - SAFEDELETE(expr_root_list_); - delete this; -} - -IR* OptWindowOrderByClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptWindowOrderByClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(order_list_); - res = new IR(IRTYPE::kOptWindowOrderByClause, OP3(TERMINAL::tOrderBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptWindowOrderByClause::deep_delete() { - SAFEDELETE(order_list_); - delete this; -} - -IR* OrderList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(order_expr_); - res = new IR(IRTYPE::kOrderList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(order_expr_); - auto tmp2 = SAFETRANSLATE(order_list_); - res = new IR(IRTYPE::kOrderList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OrderList::deep_delete() { - SAFEDELETE(order_expr_); - SAFEDELETE(order_list_); - delete this; -} - -IR* OrderExpr::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(expr_root_); - auto tmp2 = SAFETRANSLATE(opt_ordering_direction_); - res = new IR(IRTYPE::kOrderExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void OrderExpr::deep_delete() { - SAFEDELETE(opt_ordering_direction_); - SAFEDELETE(expr_root_); - delete this; -} - -IR* OptOrderingDirection::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptOrderingDirection, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptOrderingDirection, OP3(TERMINAL::tAsc, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOptOrderingDirection, OP3(TERMINAL::tDesc, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptOrderingDirection::deep_delete() { - delete this; -} - -IR* OptWindowFrameClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptWindowFrameClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(window_frame_units_); - auto tmp2 = SAFETRANSLATE(window_frame_extent_); - res = new IR(IRTYPE::kOptWindowFrameClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptWindowFrameClause::deep_delete() { - SAFEDELETE(window_frame_extent_); - SAFEDELETE(window_frame_units_); - delete this; -} - -IR* WindowFrameUnits::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kWindowFrameUnits, OP3(TERMINAL::tRows, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kWindowFrameUnits, OP3(TERMINAL::tRange, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowFrameUnits::deep_delete() { - delete this; -} - -IR* WindowFrameExtent::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(window_frame_start_); - res = new IR(IRTYPE::kWindowFrameExtent, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(window_frame_between_); - res = new IR(IRTYPE::kWindowFrameExtent, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowFrameExtent::deep_delete() { - SAFEDELETE(window_frame_start_); - SAFEDELETE(window_frame_between_); - delete this; -} - -IR* WindowFrameStart::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kWindowFrameStart, OP3(TERMINAL::tUnboundedPreceding, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(iconst_); - res = new IR(IRTYPE::kWindowFrameStart, OP3(TERMINAL::tEmpty, TERMINAL::tPreceding, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kWindowFrameStart, OP3(TERMINAL::tCurrentRow, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowFrameStart::deep_delete() { - SAFEDELETE(iconst_); - delete this; -} - -IR* WindowFrameBetween::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(window_frame_start_); - auto tmp2 = SAFETRANSLATE(window_frame_bound_); - res = new IR(IRTYPE::kWindowFrameBetween, OP3(TERMINAL::tBetween, TERMINAL::tAnd, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void WindowFrameBetween::deep_delete() { - SAFEDELETE(window_frame_bound_); - SAFEDELETE(window_frame_start_); - delete this; -} - -IR* WindowFrameBound::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(window_frame_start_); - res = new IR(IRTYPE::kWindowFrameBound, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kWindowFrameBound, OP3(TERMINAL::tUnboundedFollowing, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(iconst_); - res = new IR(IRTYPE::kWindowFrameBound, OP3(TERMINAL::tEmpty, TERMINAL::tFollowing, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowFrameBound::deep_delete() { - SAFEDELETE(window_frame_start_); - SAFEDELETE(iconst_); - delete this; -} - -IR* OptHavingClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptHavingClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kOptHavingClause, OP3(TERMINAL::tHaving, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptHavingClause::deep_delete() { - SAFEDELETE(expr_root_); - delete this; -} - -IR* OptGroupClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptGroupClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_root_list_); - auto tmp2 = SAFETRANSLATE(olap_opt_); - res = new IR(IRTYPE::kOptGroupClause, OP3(TERMINAL::tGroupBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptGroupClause::deep_delete() { - SAFEDELETE(olap_opt_); - SAFEDELETE(expr_root_list_); - delete this; -} - -IR* OlapOpt::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOlapOpt, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOlapOpt, OP3(TERMINAL::tWithRollup, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OlapOpt::deep_delete() { - delete this; -} - -IR* OptWhereClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptWhereClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(where_clause_); - res = new IR(IRTYPE::kOptWhereClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptWhereClause::deep_delete() { - SAFEDELETE(where_clause_); - delete this; -} - -IR* WhereClause::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kWhereClause, OP3(TERMINAL::tWhere, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void WhereClause::deep_delete() { - SAFEDELETE(expr_root_); - delete this; -} - -IR* OptFromClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptFromClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(from_clause_); - res = new IR(IRTYPE::kOptFromClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptFromClause::deep_delete() { - SAFEDELETE(from_clause_); - delete this; -} - -IR* FromClause::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(table_reference_list_); - res = new IR(IRTYPE::kFromClause, OP3(TERMINAL::tFrom, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void FromClause::deep_delete() { - SAFEDELETE(table_reference_list_); - delete this; -} - -IR* TableReferenceList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(table_reference_); - res = new IR(IRTYPE::kTableReferenceList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_reference_); - auto tmp2 = SAFETRANSLATE(table_reference_list_); - res = new IR(IRTYPE::kTableReferenceList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableReferenceList::deep_delete() { - SAFEDELETE(table_reference_); - SAFEDELETE(table_reference_list_); - delete this; -} - -IR* TableReference::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(table_factor_); - res = new IR(IRTYPE::kTableReference, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(joined_table_); - res = new IR(IRTYPE::kTableReference, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableReference::deep_delete() { - SAFEDELETE(table_factor_); - SAFEDELETE(joined_table_); - delete this; -} - -IR* TableFactor::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(single_table_); - res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(derived_table_); - res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(joined_table_parens_); - res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(table_reference_list_parens_); - res = new IR(IRTYPE::kTableFactor, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableFactor::deep_delete() { - SAFEDELETE(single_table_); - SAFEDELETE(derived_table_); - SAFEDELETE(joined_table_parens_); - SAFEDELETE(table_reference_list_parens_); - delete this; -} - -IR* TableReferenceListParens::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(table_reference_); - auto tmp2 = SAFETRANSLATE(table_reference_list_); - res = new IR(IRTYPE::kTableReferenceListParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - - TRANSLATEEND -} - -void TableReferenceListParens::deep_delete() { - SAFEDELETE(table_reference_list_); - SAFEDELETE(table_reference_); - delete this; -} - -IR* JoinedTableParens::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(joined_table_); - res = new IR(IRTYPE::kJoinedTableParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void JoinedTableParens::deep_delete() { - SAFEDELETE(joined_table_); - delete this; -} - -IR* DerivedTable::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(subquery_); - auto tmp2 = SAFETRANSLATE(alias_); - auto tmp3 = SAFETRANSLATE(opt_column_list_); - auto tmp4 = new IR(IRTYPE::kDerivedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kDerivedTable, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(subquery_); - auto tmp2 = SAFETRANSLATE(alias_); - auto tmp3 = SAFETRANSLATE(opt_column_list_); - auto tmp4 = new IR(IRTYPE::kDerivedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kDerivedTable, OP3(TERMINAL::tLateral, TERMINAL::tAs, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void DerivedTable::deep_delete() { - SAFEDELETE(opt_column_list_); - SAFEDELETE(alias_); - SAFEDELETE(subquery_); - delete this; -} - -IR* OptColumnList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptColumnList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_list_); - res = new IR(IRTYPE::kOptColumnList, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptColumnList::deep_delete() { - SAFEDELETE(column_list_); - delete this; -} - -IR* ColumnList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(column_name_); - res = new IR(IRTYPE::kColumnList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(column_name_); - auto tmp2 = SAFETRANSLATE(column_list_); - res = new IR(IRTYPE::kColumnList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ColumnList::deep_delete() { - SAFEDELETE(column_name_); - SAFEDELETE(column_list_); - delete this; -} - -IR* Subquery::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(query_expression_parens_); - res = new IR(IRTYPE::kSubquery, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void Subquery::deep_delete() { - SAFEDELETE(query_expression_parens_); - delete this; -} - -IR* SingleTable::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(opt_alias_); - res = new IR(IRTYPE::kSingleTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void SingleTable::deep_delete() { - SAFEDELETE(opt_alias_); - SAFEDELETE(table_name_); - delete this; -} - -IR* OptAlias::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(alias_); - res = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptAlias::deep_delete() { - SAFEDELETE(alias_); - delete this; -} - -IR* JoinedTable::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(table_reference_1_); - auto tmp2 = SAFETRANSLATE(inner_join_type_); - auto tmp3 = SAFETRANSLATE(table_reference_2_); - auto tmp4 = SAFETRANSLATE(expr_root_); - auto tmp5 = new IR(IRTYPE::kJoinedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOn, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kJoinedTableTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_reference_1_); - auto tmp2 = SAFETRANSLATE(inner_join_type_); - auto tmp3 = SAFETRANSLATE(table_reference_2_); - auto tmp4 = SAFETRANSLATE(column_list_); - auto tmp5 = new IR(IRTYPE::kJoinedTableTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tUsingOpLp, TERMINAL::tOpRp), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kJoinedTableTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(table_reference_1_); - auto tmp2 = SAFETRANSLATE(outer_join_type_); - auto tmp3 = SAFETRANSLATE(table_reference_2_); - auto tmp4 = SAFETRANSLATE(expr_root_); - auto tmp5 = new IR(IRTYPE::kJoinedTableTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOn, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kJoinedTableTmp5, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(table_reference_1_); - auto tmp2 = SAFETRANSLATE(outer_join_type_); - auto tmp3 = SAFETRANSLATE(table_reference_2_); - auto tmp4 = SAFETRANSLATE(column_list_); - auto tmp5 = new IR(IRTYPE::kJoinedTableTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tUsingOpLp, TERMINAL::tOpRp), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kJoinedTableTmp6, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(table_reference_1_); - auto tmp2 = SAFETRANSLATE(inner_join_type_); - auto tmp3 = SAFETRANSLATE(table_reference_2_); - auto tmp4 = new IR(IRTYPE::kJoinedTableTmp7, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(table_reference_1_); - auto tmp2 = SAFETRANSLATE(natural_join_type_); - auto tmp3 = SAFETRANSLATE(table_factor_); - auto tmp4 = new IR(IRTYPE::kJoinedTableTmp8, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kJoinedTable, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void JoinedTable::deep_delete() { - SAFEDELETE(expr_root_); - SAFEDELETE(table_reference_1_); - SAFEDELETE(table_reference_2_); - SAFEDELETE(inner_join_type_); - SAFEDELETE(column_list_); - SAFEDELETE(outer_join_type_); - SAFEDELETE(table_factor_); - SAFEDELETE(natural_join_type_); - delete this; -} - -IR* InnerJoinType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tInnerJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tCrossJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kInnerJoinType, OP3(TERMINAL::tStraightJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void InnerJoinType::deep_delete() { - delete this; -} - -IR* NaturalJoinType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_inner_); - res = new IR(IRTYPE::kNaturalJoinType, OP3(TERMINAL::tNatural, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_outer_); - res = new IR(IRTYPE::kNaturalJoinType, OP3(TERMINAL::tNaturalRight, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(opt_outer_); - res = new IR(IRTYPE::kNaturalJoinType, OP3(TERMINAL::tNaturalLeft, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void NaturalJoinType::deep_delete() { - SAFEDELETE(opt_inner_); - SAFEDELETE(opt_outer_); - delete this; -} - -IR* OptInner::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptInner, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptInner, OP3(TERMINAL::tInner, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptInner::deep_delete() { - delete this; -} - -IR* OptOuter::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptOuter, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptOuter, OP3(TERMINAL::tOuter, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptOuter::deep_delete() { - delete this; -} - -IR* OuterJoinType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_outer_); - res = new IR(IRTYPE::kOuterJoinType, OP3(TERMINAL::tLeft, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_outer_); - res = new IR(IRTYPE::kOuterJoinType, OP3(TERMINAL::tRight, TERMINAL::tJoin, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OuterJoinType::deep_delete() { - SAFEDELETE(opt_outer_); - delete this; -} - -IR* SelectItemList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(select_item_); - res = new IR(IRTYPE::kSelectItemList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(select_item_); - auto tmp2 = SAFETRANSLATE(select_item_list_); - res = new IR(IRTYPE::kSelectItemList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void SelectItemList::deep_delete() { - SAFEDELETE(select_item_); - SAFEDELETE(select_item_list_); - delete this; -} - -IR* SelectItem::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(table_wild_); - res = new IR(IRTYPE::kSelectItem, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_root_); - auto tmp2 = SAFETRANSLATE(opt_alias_); - res = new IR(IRTYPE::kSelectItem, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void SelectItem::deep_delete() { - SAFEDELETE(table_wild_); - SAFEDELETE(opt_alias_); - SAFEDELETE(expr_root_); - delete this; -} - -IR* TableWild::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kTableWild, OP3(TERMINAL::tOpMul, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_name_); - res = new IR(IRTYPE::kTableWild, OP3(TERMINAL::tEmpty, TERMINAL::tOpDotOpMul, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TableWild::deep_delete() { - SAFEDELETE(table_name_); - delete this; -} - -IR* OptSelectOptions::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptSelectOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(select_option_list_); - res = new IR(IRTYPE::kOptSelectOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptSelectOptions::deep_delete() { - SAFEDELETE(select_option_list_); - delete this; -} - -IR* SelectOptionList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(select_option_); - res = new IR(IRTYPE::kSelectOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(select_option_); - auto tmp2 = SAFETRANSLATE(select_option_list_); - res = new IR(IRTYPE::kSelectOptionList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void SelectOptionList::deep_delete() { - SAFEDELETE(select_option_); - SAFEDELETE(select_option_list_); - delete this; -} - -IR* SelectOption::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlNoCache, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tStraightJoin, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tHighPriority, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tDistinct, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(4) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlSmallResult, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(5) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlBigResult, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(6) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlBufferResult, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(7) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tSqlCalcFoundRows, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(8) - res = new IR(IRTYPE::kSelectOption, OP3(TERMINAL::tAll, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void SelectOption::deep_delete() { - delete this; -} - -IR* QueryExpressionParens::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(query_expression_parens_); - res = new IR(IRTYPE::kQueryExpressionParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(query_expression_); - res = new IR(IRTYPE::kQueryExpressionParens, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void QueryExpressionParens::deep_delete() { - SAFEDELETE(query_expression_parens_); - SAFEDELETE(query_expression_); - delete this; -} - -IR* OptUnionOption::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptUnionOption, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptUnionOption, OP3(TERMINAL::tDistinct, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOptUnionOption, OP3(TERMINAL::tAll, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptUnionOption::deep_delete() { - delete this; -} - -IR* OptOrderClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptOrderClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(order_clause_); - res = new IR(IRTYPE::kOptOrderClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptOrderClause::deep_delete() { - SAFEDELETE(order_clause_); - delete this; -} - -IR* OrderClause::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(order_list_); - res = new IR(IRTYPE::kOrderClause, OP3(TERMINAL::tOrderBy, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void OrderClause::deep_delete() { - SAFEDELETE(order_list_); - delete this; -} - -IR* OptLimitClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptLimitClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(limit_clause_); - res = new IR(IRTYPE::kOptLimitClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptLimitClause::deep_delete() { - SAFEDELETE(limit_clause_); - delete this; -} - -IR* LimitClause::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(limit_options_); - res = new IR(IRTYPE::kLimitClause, OP3(TERMINAL::tLimit, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void LimitClause::deep_delete() { - SAFEDELETE(limit_options_); - delete this; -} - -IR* LimitOptions::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(iconst_1_); - res = new IR(IRTYPE::kLimitOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(iconst_1_); - auto tmp2 = SAFETRANSLATE(iconst_2_); - res = new IR(IRTYPE::kLimitOptions, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void LimitOptions::deep_delete() { - SAFEDELETE(iconst_1_); - SAFEDELETE(iconst_2_); - delete this; -} - -IR* WithClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(with_list_); - res = new IR(IRTYPE::kWithClause, OP3(TERMINAL::tWith, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(with_list_); - res = new IR(IRTYPE::kWithClause, OP3(TERMINAL::tWithRecursive, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WithClause::deep_delete() { - SAFEDELETE(with_list_); - delete this; -} - -IR* WithList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(common_table_expr_); - res = new IR(IRTYPE::kWithList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(common_table_expr_); - auto tmp2 = SAFETRANSLATE(with_list_); - res = new IR(IRTYPE::kWithList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WithList::deep_delete() { - SAFEDELETE(common_table_expr_); - SAFEDELETE(with_list_); - delete this; -} - -IR* CommonTableExpr::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(opt_column_list_); - auto tmp3 = SAFETRANSLATE(subquery_); - auto tmp4 = new IR(IRTYPE::kCommonTableExprTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tAs, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kCommonTableExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - - TRANSLATEEND -} - -void CommonTableExpr::deep_delete() { - SAFEDELETE(subquery_); - SAFEDELETE(opt_column_list_); - SAFEDELETE(table_name_); - delete this; -} - -IR* ExprRootList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_root_); - res = new IR(IRTYPE::kExprRootList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_root_); - auto tmp2 = SAFETRANSLATE(expr_root_list_); - res = new IR(IRTYPE::kExprRootList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ExprRootList::deep_delete() { - SAFEDELETE(expr_root_); - SAFEDELETE(expr_root_list_); - delete this; -} - -IR* ExprRoot::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kExprRoot, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void ExprRoot::deep_delete() { - SAFEDELETE(expr_); - delete this; -} - -IR* Expr::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOr, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tXor, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tNot, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsTrue, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotTrue, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsFalse, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotFalse, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsUnknown, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotUnknown, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Expr::deep_delete() { - SAFEDELETE(expr_1_); - SAFEDELETE(expr_2_); - SAFEDELETE(bool_pri_); - delete this; -} - -IR* BoolPri::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tIsNull, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(bool_pri_); - res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tIsNotNull, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(bool_pri_); - auto tmp2 = SAFETRANSLATE(comp_op_); - auto tmp3 = SAFETRANSLATE(predicate_); - auto tmp4 = new IR(IRTYPE::kBoolPriTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(bool_pri_); - auto tmp2 = SAFETRANSLATE(comp_op_); - auto tmp3 = SAFETRANSLATE(all_subquery_); - auto tmp4 = new IR(IRTYPE::kBoolPriTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(predicate_); - res = new IR(IRTYPE::kBoolPri, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void BoolPri::deep_delete() { - SAFEDELETE(bool_pri_); - SAFEDELETE(predicate_); - SAFEDELETE(comp_op_); - SAFEDELETE(all_subquery_); - delete this; -} - -IR* Predicate::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(in_subquery_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tInOpLp, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(expr_); - auto tmp3 = SAFETRANSLATE(expr_list_); - auto tmp4 = new IR(IRTYPE::kPredicateTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tInOpLp, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotInOpLp, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(expr_); - auto tmp3 = SAFETRANSLATE(expr_list_); - auto tmp4 = new IR(IRTYPE::kPredicateTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotInOpLp, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - auto tmp3 = SAFETRANSLATE(predicate_); - auto tmp4 = new IR(IRTYPE::kPredicateTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tBetween, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - auto tmp3 = SAFETRANSLATE(predicate_); - auto tmp4 = new IR(IRTYPE::kPredicateTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotBetween, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tSoundsLike, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(simple_expr_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tLike, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(simple_expr_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotLike, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tRegexp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(11) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tNotRegexp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(12) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - res = new IR(IRTYPE::kPredicate, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Predicate::deep_delete() { - SAFEDELETE(in_subquery_); - SAFEDELETE(bit_expr_1_); - SAFEDELETE(bit_expr_2_); - SAFEDELETE(expr_); - SAFEDELETE(expr_list_); - SAFEDELETE(predicate_); - SAFEDELETE(simple_expr_); - delete this; -} - -IR* BitExpr::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpOr, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpAnd, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpShl, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpShr, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpAdd, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpSub, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpMul, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpDivide, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpMod, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(bit_expr_1_); - auto tmp2 = SAFETRANSLATE(bit_expr_2_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tOpXor, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(simple_expr_); - res = new IR(IRTYPE::kBitExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void BitExpr::deep_delete() { - SAFEDELETE(bit_expr_1_); - SAFEDELETE(bit_expr_2_); - SAFEDELETE(simple_expr_); - delete this; -} - -IR* SimpleExpr::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(columnref_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(literal_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(iconst_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(fconst_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(sconst_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(simple_expr_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpAdd, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(simple_expr_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpSub, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(simple_expr_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpNot, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tExists, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(type_cast_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(11) - auto tmp1 = SAFETRANSLATE(case_expr_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(12) - auto tmp1 = SAFETRANSLATE(columnref_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tDefaultOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(13) - auto tmp1 = SAFETRANSLATE(function_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(14) - auto tmp1 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kSimpleExpr, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void SimpleExpr::deep_delete() { - SAFEDELETE(columnref_); - SAFEDELETE(literal_); - SAFEDELETE(iconst_); - SAFEDELETE(fconst_); - SAFEDELETE(sconst_); - SAFEDELETE(simple_expr_); - SAFEDELETE(subquery_); - SAFEDELETE(type_cast_); - SAFEDELETE(case_expr_); - SAFEDELETE(function_); - SAFEDELETE(expr_); - delete this; -} - -IR* Function::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(control_function_); - res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(math_function_); - res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(string_function_); - res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(aggregate_function_); - res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(window_function_); - res = new IR(IRTYPE::kFunction, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Function::deep_delete() { - SAFEDELETE(control_function_); - SAFEDELETE(math_function_); - SAFEDELETE(string_function_); - SAFEDELETE(aggregate_function_); - SAFEDELETE(window_function_); - delete this; -} - -IR* StringFunction::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tAsciiOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tBinOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tBitLengthOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tCharLengthOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLengthOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLowerOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLtrimOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tOctOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tOrdOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tQuoteOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tReverseOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(11) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRtrimOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(12) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSpaceOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(13) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(14) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpLeadingFrom, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(15) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpTrailingFrom, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(16) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tUnhexOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(17) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tUpperOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(18) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tFindInSetOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(19) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tInstrOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(20) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLeftOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(21) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLocateOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(22) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRepeatOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(23) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRightOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(24) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSubstringOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(25) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpLeading, TERMINAL::tFrom, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(26) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLpTrailing, TERMINAL::tFrom, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(27) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tTrimOpLp, TERMINAL::tFrom, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(28) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tExportSetOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(29) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLocateOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(30) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tLpadOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(31) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tReplaceOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(32) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tRpadOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(33) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSubstringOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(34) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tSubstringIndexOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(35) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = SAFETRANSLATE(expr_4_); - auto tmp5 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kStringFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tExportSetOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(36) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = SAFETRANSLATE(expr_4_); - auto tmp5 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kStringFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tInsertOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(37) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = SAFETRANSLATE(expr_4_); - auto tmp5 = SAFETRANSLATE(expr_5_); - auto tmp6 = new IR(IRTYPE::kStringFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kStringFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kStringFunctionTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tExportSetOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp8); - CASEEND - CASESTART(38) - auto tmp1 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tCharOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(39) - auto tmp1 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tConcatOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(40) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tConcatWsOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(41) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tEltOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(42) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tFieldOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(43) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kStringFunction, OP3(TERMINAL::tMakeSetOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void StringFunction::deep_delete() { - SAFEDELETE(expr_1_); - SAFEDELETE(expr_2_); - SAFEDELETE(expr_3_); - SAFEDELETE(expr_4_); - SAFEDELETE(expr_5_); - SAFEDELETE(expr_list_); - delete this; -} - -IR* MathFunction::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tPiOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAbsOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAcosOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAsinOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAtanOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tCeilingOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tCosOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tCotOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tDegreesOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tExpOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(11) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tFloorOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(12) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tHexOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(13) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tLnOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(14) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRadiansOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(15) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(16) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRoundOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(17) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tSignOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(18) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tSinOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(19) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tSqrtOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(20) - auto tmp1 = SAFETRANSLATE(expr_1_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tTanOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(21) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tAtanOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(22) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tFormatOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(23) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tLogOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(24) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tModOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(25) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tPowOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(26) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRoundOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(27) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tTruncateOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(28) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kMathFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tConvOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void MathFunction::deep_delete() { - SAFEDELETE(expr_1_); - SAFEDELETE(expr_2_); - SAFEDELETE(expr_3_); - delete this; -} - -IR* WindowFunction::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tRowNumberOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tRankOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tDenseRankOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tCumeDistOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tPercentRankOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(iconst_); - auto tmp2 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tNtileOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_lead_lag_info_); - auto tmp3 = SAFETRANSLATE(opt_null_treatment_); - auto tmp4 = SAFETRANSLATE(windowing_clause_); - auto tmp5 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kWindowFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tLeadOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_lead_lag_info_); - auto tmp3 = SAFETRANSLATE(opt_null_treatment_); - auto tmp4 = SAFETRANSLATE(windowing_clause_); - auto tmp5 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp4); - auto tmp6 = new IR(IRTYPE::kWindowFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp5); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tLagOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp6); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_null_treatment_); - auto tmp3 = SAFETRANSLATE(windowing_clause_); - auto tmp4 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tFirstValueOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_null_treatment_); - auto tmp3 = SAFETRANSLATE(windowing_clause_); - auto tmp4 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tLastValueOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(iconst_); - auto tmp3 = SAFETRANSLATE(opt_from_first_last_); - auto tmp4 = SAFETRANSLATE(opt_null_treatment_); - auto tmp5 = SAFETRANSLATE(windowing_clause_); - auto tmp6 = new IR(IRTYPE::kWindowFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kWindowFunctionTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kWindowFunctionTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kWindowFunction, OP3(TERMINAL::tNthValueOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp8); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowFunction::deep_delete() { - SAFEDELETE(windowing_clause_); - SAFEDELETE(iconst_); - SAFEDELETE(opt_null_treatment_); - SAFEDELETE(opt_lead_lag_info_); - SAFEDELETE(expr_); - SAFEDELETE(opt_from_first_last_); - delete this; -} - -IR* OptNullTreatment::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptNullTreatment, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptNullTreatment, OP3(TERMINAL::tRespectNulls, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOptNullTreatment, OP3(TERMINAL::tIgnoreNulls, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptNullTreatment::deep_delete() { - delete this; -} - -IR* OptFromFirstLast::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptFromFirstLast, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptFromFirstLast, OP3(TERMINAL::tFromFirst, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kOptFromFirstLast, OP3(TERMINAL::tFromLast, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptFromFirstLast::deep_delete() { - delete this; -} - -IR* OptLeadLagInfo::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptLeadLagInfo, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(lead_lag_info_); - res = new IR(IRTYPE::kOptLeadLagInfo, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptLeadLagInfo::deep_delete() { - SAFEDELETE(lead_lag_info_); - delete this; -} - -IR* LeadLagInfo::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(iconst_); - res = new IR(IRTYPE::kLeadLagInfo, OP3(TERMINAL::tOpComma, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(iconst_); - auto tmp2 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kLeadLagInfo, OP3(TERMINAL::tOpComma, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void LeadLagInfo::deep_delete() { - SAFEDELETE(iconst_); - SAFEDELETE(expr_); - delete this; -} - -IR* AggregateFunction::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_distinct_); - auto tmp2 = SAFETRANSLATE(expr_); - auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); - auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tAvgOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tBitAndOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tBitOrOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(3) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tBitXorOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(4) - auto tmp1 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tCountOpLpOpMulOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tCountOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(6) - auto tmp1 = SAFETRANSLATE(expr_list_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tCountOpLpDistinct, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(opt_distinct_); - auto tmp2 = SAFETRANSLATE(expr_); - auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); - auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tMinOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(8) - auto tmp1 = SAFETRANSLATE(opt_distinct_); - auto tmp2 = SAFETRANSLATE(expr_); - auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); - auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tMaxOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(9) - auto tmp1 = SAFETRANSLATE(opt_distinct_); - auto tmp2 = SAFETRANSLATE(expr_); - auto tmp3 = SAFETRANSLATE(opt_windowing_clause_); - auto tmp4 = new IR(IRTYPE::kAggregateFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp2, tmp3); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tSumOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(10) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tStdOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(11) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tStddevSampOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(12) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tVarianceOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(13) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(opt_windowing_clause_); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tVarSampOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - CASESTART(14) - auto tmp1 = SAFETRANSLATE(opt_distinct_); - auto tmp2 = SAFETRANSLATE(expr_list_); - auto tmp3 = SAFETRANSLATE(opt_order_clause_); - auto tmp4 = SAFETRANSLATE(opt_gconcat_separator_); - auto tmp5 = SAFETRANSLATE(opt_windowing_clause_); - auto tmp6 = new IR(IRTYPE::kAggregateFunctionTmp2, OP3(TERMINAL::tEmpty, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp4, tmp5); - auto tmp7 = new IR(IRTYPE::kAggregateFunctionTmp3, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp3, tmp6); - auto tmp8 = new IR(IRTYPE::kAggregateFunctionTmp4, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp2, tmp7); - res = new IR(IRTYPE::kAggregateFunction, OP3(TERMINAL::tGroupConcatOpLp, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp8); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void AggregateFunction::deep_delete() { - SAFEDELETE(opt_windowing_clause_); - SAFEDELETE(expr_); - SAFEDELETE(opt_distinct_); - SAFEDELETE(expr_list_); - SAFEDELETE(opt_gconcat_separator_); - SAFEDELETE(opt_order_clause_); - delete this; -} - -IR* OptGconcatSeparator::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptGconcatSeparator, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(sconst_); - res = new IR(IRTYPE::kOptGconcatSeparator, OP3(TERMINAL::tSeparator, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptGconcatSeparator::deep_delete() { - SAFEDELETE(sconst_); - delete this; -} - -IR* OptDistinct::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptDistinct, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kOptDistinct, OP3(TERMINAL::tDistinct, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptDistinct::deep_delete() { - delete this; -} - -IR* OptWindowingClause::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptWindowingClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(windowing_clause_); - res = new IR(IRTYPE::kOptWindowingClause, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptWindowingClause::deep_delete() { - SAFEDELETE(windowing_clause_); - delete this; -} - -IR* WindowingClause::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(window_name_or_spec_); - res = new IR(IRTYPE::kWindowingClause, OP3(TERMINAL::tOver, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void WindowingClause::deep_delete() { - SAFEDELETE(window_name_or_spec_); - delete this; -} - -IR* WindowNameOrSpec::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(window_name_); - res = new IR(IRTYPE::kWindowNameOrSpec, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(window_spec_); - res = new IR(IRTYPE::kWindowNameOrSpec, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WindowNameOrSpec::deep_delete() { - SAFEDELETE(window_name_); - SAFEDELETE(window_spec_); - delete this; -} - -IR* ControlFunction::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - auto tmp3 = SAFETRANSLATE(expr_3_); - auto tmp4 = new IR(IRTYPE::kControlFunctionTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp2, tmp3); - res = new IR(IRTYPE::kControlFunction, OP3(TERMINAL::tIfOpLp, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp4); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kControlFunction, OP3(TERMINAL::tIfnullOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kControlFunction, OP3(TERMINAL::tNullifOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ControlFunction::deep_delete() { - SAFEDELETE(expr_1_); - SAFEDELETE(expr_2_); - SAFEDELETE(expr_3_); - delete this; -} - -IR* CaseExpr::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(opt_expr_); - auto tmp2 = SAFETRANSLATE(when_clasue_list_); - auto tmp3 = SAFETRANSLATE(opt_else_); - auto tmp4 = new IR(IRTYPE::kCaseExprTmp1, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEnd), tmp2, tmp3); - res = new IR(IRTYPE::kCaseExpr, OP3(TERMINAL::tCase, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp4); - - TRANSLATEEND -} - -void CaseExpr::deep_delete() { - SAFEDELETE(opt_else_); - SAFEDELETE(when_clasue_list_); - SAFEDELETE(opt_expr_); - delete this; -} - -IR* WhenClasueList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(when_list_); - res = new IR(IRTYPE::kWhenClasueList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(when_list_); - auto tmp2 = SAFETRANSLATE(when_clasue_list_); - res = new IR(IRTYPE::kWhenClasueList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void WhenClasueList::deep_delete() { - SAFEDELETE(when_list_); - SAFEDELETE(when_clasue_list_); - delete this; -} - -IR* WhenList::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(expr_1_); - auto tmp2 = SAFETRANSLATE(expr_2_); - res = new IR(IRTYPE::kWhenList, OP3(TERMINAL::tWhen, TERMINAL::tThen, TERMINAL::tEmpty), tmp1, tmp2); - - TRANSLATEEND -} - -void WhenList::deep_delete() { - SAFEDELETE(expr_1_); - SAFEDELETE(expr_2_); - delete this; -} - -IR* OptExpr::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kOptExpr, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptExpr::deep_delete() { - SAFEDELETE(expr_); - delete this; -} - -IR* OptElse::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptElse, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kOptElse, OP3(TERMINAL::tElse, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptElse::deep_delete() { - SAFEDELETE(expr_); - delete this; -} - -IR* TypeCast::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(cast_type_); - res = new IR(IRTYPE::kTypeCast, OP3(TERMINAL::tCastOpLp, TERMINAL::tAs, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(cast_type_); - res = new IR(IRTYPE::kTypeCast, OP3(TERMINAL::tConvertOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void TypeCast::deep_delete() { - SAFEDELETE(cast_type_); - SAFEDELETE(expr_); - delete this; -} - -IR* CastType::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tBinary, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tChar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tNchar, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tSigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(4) - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tUnsigned, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(5) - auto tmp1 = SAFETRANSLATE(float_options_); - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tDecimal, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(6) - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tReal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(7) - auto tmp1 = SAFETRANSLATE(opt_field_length_); - res = new IR(IRTYPE::kCastType, OP3(TERMINAL::tFloat, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void CastType::deep_delete() { - SAFEDELETE(opt_field_length_); - SAFEDELETE(float_options_); - delete this; -} - -IR* FloatOptions::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kFloatOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(field_length_); - res = new IR(IRTYPE::kFloatOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(precision_); - res = new IR(IRTYPE::kFloatOptions, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void FloatOptions::deep_delete() { - SAFEDELETE(field_length_); - SAFEDELETE(precision_); - delete this; -} - -IR* Precision::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(iconst_1_); - auto tmp2 = SAFETRANSLATE(iconst_2_); - res = new IR(IRTYPE::kPrecision, OP3(TERMINAL::tOpLp, TERMINAL::tOpComma, TERMINAL::tOpRp), tmp1, tmp2); - - TRANSLATEEND -} - -void Precision::deep_delete() { - SAFEDELETE(iconst_1_); - SAFEDELETE(iconst_2_); - delete this; -} - -IR* OptFieldLength::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kOptFieldLength, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(field_length_); - res = new IR(IRTYPE::kOptFieldLength, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void OptFieldLength::deep_delete() { - SAFEDELETE(field_length_); - delete this; -} - -IR* FieldLength::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(iconst_); - res = new IR(IRTYPE::kFieldLength, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void FieldLength::deep_delete() { - SAFEDELETE(iconst_); - delete this; -} - -IR* Literal::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tNull, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tFalse, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tTrue, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Literal::deep_delete() { - delete this; -} - -IR* Columnref::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(column_name_); - res = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(table_name_); - auto tmp2 = SAFETRANSLATE(column_name_); - res = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tOpDot, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void Columnref::deep_delete() { - SAFEDELETE(column_name_); - SAFEDELETE(table_name_); - delete this; -} - -IR* CompOp::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpEqual, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(1) - res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpGreatereq, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(2) - res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpGreaterthan, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(3) - res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpLesseq, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(4) - res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpLessthan, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - CASESTART(5) - res = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpNotequal, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void CompOp::deep_delete() { - delete this; -} - -IR* AllSubquery::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kAllSubquery, OP3(TERMINAL::tAll, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kAllSubquery, OP3(TERMINAL::tAny, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(2) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kAllSubquery, OP3(TERMINAL::tSome, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void AllSubquery::deep_delete() { - SAFEDELETE(subquery_); - delete this; -} - -IR* InSubquery::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kInSubquery, OP3(TERMINAL::tIn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(subquery_); - res = new IR(IRTYPE::kInSubquery, OP3(TERMINAL::tNotIn, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void InSubquery::deep_delete() { - SAFEDELETE(subquery_); - delete this; -} - -IR* ExprList::translate() { - TRANSLATESTART - - SWITCHSTART - CASESTART(0) - auto tmp1 = SAFETRANSLATE(expr_); - res = new IR(IRTYPE::kExprList, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - CASEEND - CASESTART(1) - auto tmp1 = SAFETRANSLATE(expr_); - auto tmp2 = SAFETRANSLATE(expr_list_); - res = new IR(IRTYPE::kExprList, OP3(TERMINAL::tEmpty, TERMINAL::tOpComma, TERMINAL::tEmpty), tmp1, tmp2); - CASEEND - SWITCHEND - - TRANSLATEEND -} - -void ExprList::deep_delete() { - SAFEDELETE(expr_); - SAFEDELETE(expr_list_); - delete this; -} - -IR* Iconst::translate(){ - TRANSLATESTART - - res = new IR(kIconst, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - res->long_val_ = this->long_val_; - - TRANSLATEEND -} - -void Iconst::deep_delete(){ - delete this; -} - -IR* Fconst::translate(){ - TRANSLATESTART - - res = new IR(kFconst, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - res->float_val_ = this->float_val_; - - TRANSLATEEND -} - -void Fconst::deep_delete(){ - delete this; -} - -IR* Sconst::translate(){ - TRANSLATESTART - - res = new IR(kSconst, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - res->str_val_ = this->str_val_; - - TRANSLATEEND -} - -void Sconst::deep_delete(){ - delete this; -} - -IR* Ident::translate(){ - TRANSLATESTART - - res = new IR(kIdent, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - res->str_val_ = this->str_val_; - - TRANSLATEEND -} - -void Ident::deep_delete(){ - delete this; -} - -IR* Alias::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kAlias, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void Alias::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - -IR* ColumnName::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kColumnName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void ColumnName::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - -IR* WindowName::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kWindowName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void WindowName::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - -IR* TableName::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kTableName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void TableName::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - -IR* ConstraintName::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kConstraintName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void ConstraintName::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - -IR* IndexName::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kIndexName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void IndexName::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - -IR* ViewName::translate() { - TRANSLATESTART - - auto tmp1 = SAFETRANSLATE(ident_); - res = new IR(IRTYPE::kViewName, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), tmp1, nullptr); - - TRANSLATEEND -} - -void ViewName::deep_delete() { - SAFEDELETE(ident_); - delete this; -} - diff --git a/src/connector.cpp b/src/connector.cpp deleted file mode 100755 index 6ee4746..0000000 --- a/src/connector.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "../include/connector.h" - -static void myproc(void* arg, const PGresult* res) { - return; -} - -Connector::Connector(const char* host, const char* userName, const char* password, unsigned int port, const char* serverName) { - conninfo_ += "host=" + string(host) + " "; - conninfo_ += "user=" + string(userName) + " "; - conninfo_ += "password=" + string(password) + " "; - conninfo_ += "port=" + to_string(port); - - serverName_ = serverName; - - return; -} - -bool Connector::start_db(const char* file, char* const options[]) { - pid_t dbPid = get_pid_by_name(); - - if (dbPid != 1) { - SQLSTATUS status = reset_db(); - - if (status == SQLSTATUS::ssNormal) { - return true; - } - - return false; - } - - int i = 0; - while (dbPid == 1 && i < 10) { - pid_t pid = fork(); - - if (pid == 0) { - execvp(file, options); - exit(1); - } - else { - wait(NULL); - sleep(5); - } - - dbPid = get_pid_by_name(); - i++; - } - - if (dbPid != 1) { - SQLSTATUS status = reset_db(); - - if (status == SQLSTATUS::ssNormal) { - return true; - } - } - - return false; -} -bool Connector::close_db() { - pid_t dbPid = get_pid_by_name(); - int res = -1; - - if (dbPid != 1) { - res = kill(dbPid, SIGKILL); - } - - if (res == -1) { - return false; - } - - sleep(5); - - return true; -} - -SQLSTATUS Connector::execute(const char* sql) { - SQLSTATUS res = SQLSTATUS::ssNormal; - string curConninfo = "dbname=test " + conninfo_; - - PGconn* conn = PQconnectdb(curConninfo.c_str()); - if (PQstatus(conn) != CONNECTION_OK) { - PQfinish(conn); - return SQLSTATUS::ssConnectFailed; - } - - PQsetNoticeReceiver(conn, myproc, nullptr); - - reset_database(conn); - - PGresult* pgres = PQexec(conn, sql); - if (PQstatus(conn) != CONNECTION_OK) { - res = SQLSTATUS::ssServerCrash; - } - else if (PQresultStatus(pgres) != PGRES_COMMAND_OK && PQresultStatus(pgres) != PGRES_TUPLES_OK) { - res = SQLSTATUS::ssSemanticError; - } - - PQclear(pgres); - PQfinish(conn); - - return res; -} - -void Connector::reset_database(PGconn* conn) { - PGresult* res = PQexec(conn, "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"); - PQclear(res); - - return; -} - -SQLSTATUS Connector::reset_db() { - SQLSTATUS res = SQLSTATUS::ssNormal; - string curConninfo = "dbname=postgres " + conninfo_; - - PGconn* conn = PQconnectdb(curConninfo.c_str()); - if (PQstatus(conn) != CONNECTION_OK) { - PQfinish(conn); - return SQLSTATUS::ssConnectFailed; - } - - PQsetNoticeReceiver(conn, myproc, nullptr); - - int i = 0; - - PGresult* pgres = PQexec(conn, "DROP DATABASE IF EXISTS test;"); - PQclear(pgres); - pgres = PQexec(conn, "CREATE DATABASE IF NOT EXISTS test;"); - PQclear(pgres); - - PQfinish(conn); - - res = execute("SELECT 1;"); - - return res; -} - -pid_t Connector::get_pid_by_name() { - DIR* dir; - struct dirent* ptr; - FILE* fp; - char filepath[50]; - char cur_task_name[50]; - char buf[BUF_SIZE]; - - pid_t pid = 1; - - dir = opendir("/proc"); - if (NULL != dir) - { - while ((ptr = readdir(dir)) != NULL) - { - - if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) - continue; - if (DT_DIR != ptr->d_type) - continue; - - sprintf(filepath, "/proc/%s/status", ptr->d_name); - fp = fopen(filepath, "r"); - if (NULL != fp) - { - if (fgets(buf, BUF_SIZE - 1, fp) == NULL) { - fclose(fp); - continue; - } - sscanf(buf, "%*s %s", cur_task_name); - - if (!strcmp(serverName_.c_str(), cur_task_name)) { - sscanf(ptr->d_name, "%d", &pid); - } - fclose(fp); - } - } - closedir(dir); - } - - return pid; -} diff --git a/src/instantiate.cpp b/src/instantiate.cpp deleted file mode 100755 index f1f80cf..0000000 --- a/src/instantiate.cpp +++ /dev/null @@ -1,3555 +0,0 @@ -#include "../include/instantiate.h" - -using namespace std; - -vector> Column::compatibility_ = {}; -map Column::typeTranslation_ = { - {TERMINAL::tInt, ColumnType::ctInt}, - {TERMINAL::tTinyint, ColumnType::ctTinyInt}, - {TERMINAL::tSmallint, ColumnType::ctSmallInt}, - {TERMINAL::tMediumint, ColumnType::ctMediumInt}, - {TERMINAL::tBigint, ColumnType::ctBigInt}, - {TERMINAL::tReal, ColumnType::ctReal}, - {TERMINAL::tDouble, ColumnType::ctDouble}, - {TERMINAL::tFloat, ColumnType::ctFloat}, - {TERMINAL::tDecimal, ColumnType::ctDecimal}, - {TERMINAL::tNumeric, ColumnType::ctNumeric}, - {TERMINAL::tFixed, ColumnType::ctFixed}, - - {TERMINAL::tBool, ColumnType::ctBool}, - {TERMINAL::tBoolean, ColumnType::ctBoolean}, - - {TERMINAL::tChar, ColumnType::ctChar}, - {TERMINAL::tBinary, ColumnType::ctBinary}, - {TERMINAL::tVarchar, ColumnType::ctVarchar}, - {TERMINAL::tVarbinary, ColumnType::ctVarbinary}, - {TERMINAL::tLongVarbinary, ColumnType::ctLongVarbinary}, - {TERMINAL::tTinyblob, ColumnType::ctTinyBlob}, - {TERMINAL::tMediumblob, ColumnType::ctMediumBlob}, - {TERMINAL::tLongblob, ColumnType::ctLongBlob}, - {TERMINAL::tBlob, ColumnType::ctBlob}, - {TERMINAL::tTinytext, ColumnType::ctTinyText}, - {TERMINAL::tMediumtext, ColumnType::ctMediumText}, - {TERMINAL::tLongtext, ColumnType::ctLongText}, - {TERMINAL::tText, ColumnType::ctText} -}; -map Column::typeToBasicType_ = { - {ColumnType::ctNull, ColumnBasicType::ctBool}, - - {ColumnType::ctInt, ColumnBasicType::ctNumber}, - {ColumnType::ctTinyInt, ColumnBasicType::ctNumber}, - {ColumnType::ctSmallInt, ColumnBasicType::ctNumber}, - {ColumnType::ctMediumInt, ColumnBasicType::ctNumber}, - {ColumnType::ctBigInt, ColumnBasicType::ctNumber}, - {ColumnType::ctReal, ColumnBasicType::ctNumber}, - {ColumnType::ctDouble, ColumnBasicType::ctNumber}, - {ColumnType::ctFloat, ColumnBasicType::ctNumber}, - {ColumnType::ctDecimal, ColumnBasicType::ctNumber}, - {ColumnType::ctNumeric, ColumnBasicType::ctNumber}, - {ColumnType::ctFixed, ColumnBasicType::ctNumber}, - - {ColumnType::ctBool, ColumnBasicType::ctBool}, - {ColumnType::ctBoolean, ColumnBasicType::ctBool}, - - {ColumnType::ctChar, ColumnBasicType::ctString}, - {ColumnType::ctBinary, ColumnBasicType::ctString}, - {ColumnType::ctVarchar, ColumnBasicType::ctString}, - {ColumnType::ctVarbinary, ColumnBasicType::ctString}, - {ColumnType::ctLongVarbinary, ColumnBasicType::ctString}, - {ColumnType::ctTinyBlob, ColumnBasicType::ctString}, - {ColumnType::ctMediumBlob, ColumnBasicType::ctString}, - {ColumnType::ctLongBlob, ColumnBasicType::ctString}, - {ColumnType::ctBlob, ColumnBasicType::ctString}, - {ColumnType::ctTinyText, ColumnBasicType::ctString}, - {ColumnType::ctMediumText, ColumnBasicType::ctString}, - {ColumnType::ctLongText, ColumnBasicType::ctString}, - {ColumnType::ctText, ColumnBasicType::ctString} -}; - -Instantiator::Instantiator() { - random_device rd; - srand(rd()); - - IRTrim_ = new IRTrim(this); - exprInstantiator_ = new ExprInstantiator(this); - globalStatusManger_ = new GlobalStatusManger(); - - startTime = chrono::steady_clock::now(); - - return; -} -Instantiator::~Instantiator() { - delete IRTrim_; - delete globalStatusManger_; - delete exprInstantiator_; - - return; -} - -unsigned int Instantiator::get_duration_ms(){ - chrono::time_point curTime = chrono::steady_clock::now(); - - return chrono::duration_cast(curTime - startTime).count(); -} - -bool Instantiator::instantaite_sql(IR* root) { - int maxCapacity = calc_capacity(root); - int curCapacity = calc_node(root); - - if (curCapacity > maxCapacity) { - return false; - } - - instantiate_parse_toplevel(NT_check(root, IRTYPE::kParseToplevel)); - - return true; -} -int Instantiator::calc_capacity(IR* root) { - int tmp_node_upper_limit = 0; - - unsigned int curCapacity = CAPACITYBASE * pow(CAPACITYGROWTHRATE, static_cast(get_duration_ms() / TIMETHRESHOLD)); - curCapacity = curCapacity > MAXCAPACITY ? MAXCAPACITY : curCapacity; - - if (root->type_ != IRTYPE::kParseToplevel) - return 0; - - IR* stmtmulti = root->left_; - - while (stmtmulti) { - tmp_node_upper_limit += curCapacity; - stmtmulti = stmtmulti->right_; - } - - return tmp_node_upper_limit; -} -int Instantiator::calc_node(IR* root) { - int res = 0; - - if (root->left_) res += calc_node(root->left_); - if (root->right_) res += calc_node(root->right_); - - return res + 1; -} - -void Instantiator::instantiate_parse_toplevel(IR* parse_toplevel) { - assert(parse_toplevel != nullptr && parse_toplevel->type_ == IRTYPE::kParseToplevel); - IR* stmtmulti = NT_check(parse_toplevel->left_, IRTYPE::kStmtmulti); - - while (stmtmulti != nullptr) { - IR* stmt = NT_check(stmtmulti->left_, IRTYPE::kStmt); - - switch (stmt->left_->type_) { - case IRTYPE::kSelectStmt: { - instantiate_select_stmt(NT_check(stmt->left_, IRTYPE::kSelectStmt)); - break; - } - case IRTYPE::kCreateTableStmt: { - instantiate_create_table_stmt(NT_check(stmt->left_, IRTYPE::kCreateTableStmt)); - break; - } - case IRTYPE::kCreateViewStmt: { - instantiate_create_view_stmt(NT_check(stmt->left_, IRTYPE::kCreateViewStmt)); - break; - } - case IRTYPE::kCreateIndexStmt: { - instantiate_create_index_stmt(NT_check(stmt->left_, IRTYPE::kCreateIndexStmt)); - break; - } - case IRTYPE::kDropIndexStmt: { - instantiate_drop_index_stmt(NT_check(stmt->left_, IRTYPE::kDropIndexStmt)); - break; - } - case IRTYPE::kDropTableStmt: { - instantiate_drop_table_or_view_stmt(NT_check(stmt->left_, IRTYPE::kDropTableStmt), IdentifierType::iTable); - break; - } - case IRTYPE::kDropViewStmt: { - instantiate_drop_table_or_view_stmt(NT_check(stmt->left_, IRTYPE::kDropViewStmt), IdentifierType::iView); - break; - } - case IRTYPE::kDeleteStmt: { - instantiate_delete_stmt(NT_check(stmt->left_, IRTYPE::kDeleteStmt)); - break; - } - case IRTYPE::kUpdateStmt: { - instantiate_update_stmt(NT_check(stmt->left_, IRTYPE::kUpdateStmt)); - break; - } - case IRTYPE::kInsertStmt: { - instantiate_insert_stmt(NT_check(stmt->left_, IRTYPE::kInsertStmt)); - break; - } - case IRTYPE::kAlterTableStmt: { - instantiate_alter_table_stmt(NT_check(stmt->left_, IRTYPE::kAlterTableStmt)); - break; - } - default: { - return; - } - } - - stmtmulti = stmtmulti->right_; - } - - globalStatusManger_->reset_status(); - - return; -} - -void Instantiator::instantiate_alter_table_stmt(IR* alter_table_stmt) { - IR* table_name = NT_check(alter_table_stmt->left_, IRTYPE::kTableName); - IR* alter_list = NT_check(alter_table_stmt->right_, IRTYPE::kAlterList); - - vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); - if (tables.empty()) { - return; - } - - Table* table = tables[rand() % tables.size()]; - instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); - - IR* curNode = alter_list; - while (curNode != nullptr) { - IR* alter_list_item = NT_check(curNode->left_, IRTYPE::kAlterListItem); - instantiate_alter_list_item(alter_list_item, table); - - curNode = curNode->right_; - } - - return; -} -void Instantiator::instantiate_alter_list_item(IR* alter_list_item, Table* table) { - switch (alter_list_item->op_->prefix_) { - case TERMINAL::tAddColumn: { - IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); - IR* field_def = NT_check(alter_list_item->right_->left_, IRTYPE::kFieldDef); - IR* opt_place = NT_check(alter_list_item->right_->right_, IRTYPE::kOptPlace); - - IR* data_type = NT_check(field_def->left_, IRTYPE::kDataType); - IR* opt_column_attribute_list = NT_check(field_def->right_, IRTYPE::kOptColumnAttributeList); - - ColumnType type = instantiate_data_type(data_type); - - name_t newColumnName = table->get_acce_column_name(); - Column* column = new Column(newColumnName, type); - - instantiate_ident(column_name, IdentifierType::iColumn, newColumnName); - - if (opt_place->left_ != nullptr) { - IR* tmp_column_name = NT_check(opt_place->left_, IRTYPE::kColumnName); - - Column* tmp_column = table->columns_[rand() % table->columns_.size()]; - instantiate_ident(tmp_column_name, IdentifierType::iColumn, tmp_column->identifierName_); - - table->add_column(column, tmp_column); - } - else if(opt_place->op_->prefix_ == TERMINAL::tFirst) { - table->add_column_first(column); - } - else { - table->add_column(column); - } - - if (opt_column_attribute_list->left_ != nullptr) { - IR* curNode = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); - - while (curNode != nullptr) { - IR* column_attribute = NT_check(curNode->left_, IRTYPE::kColumnAttribute); - instantiate_column_attribute(column_attribute, column, table); - - curNode = curNode->right_; - } - } - - break; - } - case TERMINAL::tAddColumnOpLp: { - IR* table_element_list = NT_check(alter_list_item->left_, IRTYPE::kTableElementList); - - instantiate_table_element_list(table_element_list, table); - - break; - } - case TERMINAL::tAdd: { - IR* table_constraint_def = NT_check(alter_list_item->left_, IRTYPE::kTableConstraintDef); - - if (table_constraint_def->op_->prefix_ == TERMINAL::tIndex) { - instantiate_table_constraint_def_index(table_constraint_def, table); - } - else if (table_constraint_def->op_->middle_ == tForeignKey) { - instantiate_table_constraint_def_foreign_key(table_constraint_def, table); - } - else if (table_constraint_def->right_->type_ == IRTYPE::kCheckConstraint) { - instantiate_table_constraint_def_check(table_constraint_def, table); - } - else { - instantiate_table_constraint_def_key(table_constraint_def, table); - } - - break; - } - case TERMINAL::tChangeColumn: { - IR* column_name_1 = nullptr; - IR* column_name_2 = nullptr; - IR* field_def = nullptr; - IR* opt_place = nullptr; - - IR* unknown = nullptr; - - column_name_1 = NT_check(alter_list_item->left_, IRTYPE::kColumnName); - unknown = alter_list_item->right_; - - column_name_2 = NT_check(unknown->left_, IRTYPE::kColumnName); - unknown = unknown->right_; - - field_def = NT_check(unknown->left_, IRTYPE::kFieldDef); - opt_place = NT_check(unknown->right_, IRTYPE::kOptPlace); - - IR* data_type = NT_check(field_def->left_, IRTYPE::kDataType); - IR* opt_column_attribute_list = NT_check(field_def->right_, IRTYPE::kOptColumnAttributeList); - - Column* column = table->columns_[rand() % table->columns_.size()]; - column->columnType_ = instantiate_data_type(data_type); - - name_t newColumnName = table->get_acce_column_name(); - instantiate_ident(column_name_1, IdentifierType::iColumn, column->identifierName_); - instantiate_ident(column_name_2, IdentifierType::iColumn, newColumnName); - - table->column_rename(column, column->identifierName_, newColumnName); - - if (opt_place->left_ != nullptr) { - IR* tmp_column_name = NT_check(opt_place->left_, IRTYPE::kColumnName); - - Column* tmp_column = table->columns_[rand() % table->columns_.size()]; - - if (tmp_column != column) { - instantiate_ident(tmp_column_name, IdentifierType::iColumn, tmp_column->identifierName_); - table->move_column(column, tmp_column); - } - else { - deep_delete(opt_place->left_); - opt_place->left_ = nullptr; - opt_place->op_->prefix_ = TERMINAL::tEmpty; - } - } - else if (opt_place->op_->prefix_ == TERMINAL::tFirst) { - table->move_column_first(column); - } - - if (opt_column_attribute_list->left_ != nullptr) { - IR* curNode = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); - - while (curNode != nullptr) { - IR* column_attribute = NT_check(curNode->left_, IRTYPE::kColumnAttribute); - instantiate_column_attribute(column_attribute, column, table); - - curNode = curNode->right_; - } - } - - break; - } - case TERMINAL::tModifyColumn: { - IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); - IR* field_def = NT_check(alter_list_item->right_->left_, IRTYPE::kFieldDef); - IR* opt_place = NT_check(alter_list_item->right_->right_, IRTYPE::kOptPlace); - - IR* data_type = NT_check(field_def->left_, IRTYPE::kDataType); - IR* opt_column_attribute_list = NT_check(field_def->right_, IRTYPE::kOptColumnAttributeList); - - Column* column = table->columns_[rand() % table->columns_.size()]; - column->columnType_ = instantiate_data_type(data_type); - instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); - - if (opt_place->left_ != nullptr) { - IR* tmp_column_name = NT_check(opt_place->left_, IRTYPE::kColumnName); - - Column* tmp_column = table->columns_[rand() % table->columns_.size()]; - - if (tmp_column != column) { - instantiate_ident(tmp_column_name, IdentifierType::iColumn, tmp_column->identifierName_); - table->move_column(column, tmp_column); - } - else { - deep_delete(opt_place->left_); - opt_place->left_ = nullptr; - opt_place->op_->prefix_ = TERMINAL::tEmpty; - } - } - else if (opt_place->op_->prefix_ == TERMINAL::tFirst) { - table->move_column_first(column); - } - - if (opt_column_attribute_list->left_ != nullptr) { - IR* curNode = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); - - while (curNode != nullptr) { - IR* column_attribute = NT_check(curNode->left_, IRTYPE::kColumnAttribute); - instantiate_column_attribute(column_attribute, column, table); - - curNode = curNode->right_; - } - } - - break; - } - case TERMINAL::tDropColumn: { - IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); - - if (table->columns_.size() <= 1) { - return; - } - - Column* column = table->columns_[rand() % table->columns_.size()]; - instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); - - table->drop_column(column); - - break; - } - case TERMINAL::tDropForeignKey: { - IR* constraint_name = NT_check(alter_list_item->left_, IRTYPE::kConstraintName); - - Constraint* constraint = nullptr; - for (Constraint* c : table->constraints_) { - if (c->constraintType_ != ConstraintType::ctForeignKey) { - continue; - } - - constraint = c; - break; - } - - if (constraint == nullptr) { - return; - } - - instantiate_ident(constraint_name, IdentifierType::iConstraint, constraint->identifierName_); - - table->drop_constraint(constraint); - - break; - } - case TERMINAL::tDropPrimaryKey: { - if (table->hasPrimaryKey_ == false) { - return; - } - - Constraint* constraint = nullptr; - for (Constraint* c : table->constraints_) { - if (c->constraintType_ != ConstraintType::ctPrimaryKey) { - continue; - } - - constraint = c; - break; - } - - assert(constraint != nullptr); - - table->drop_constraint(constraint); - table->hasPrimaryKey_ = false; - - break; - } - case TERMINAL::tDropIndex: { - IR* index_name = NT_check(alter_list_item->left_, IRTYPE::kIndexName); - - if (table->indexes_.empty()) { - return; - } - - Index* index = table->indexes_[rand() % table->indexes_.size()]; - instantiate_ident(index_name, IdentifierType::iIndex, index->identifierName_); - - table->drop_index(index); - - break; - } - case TERMINAL::tDropCheck: { - IR* constraint_name = NT_check(alter_list_item->left_, IRTYPE::kConstraintName); - - Constraint* constraint = nullptr; - for (Constraint* c : table->constraints_) { - if (c->constraintType_ != ConstraintType::ctCheck) { - continue; - } - - constraint = c; - break; - } - - if (constraint == nullptr) { - return; - } - - instantiate_ident(constraint_name, IdentifierType::iConstraint, constraint->identifierName_); - - table->drop_constraint(constraint); - - break; - } - case TERMINAL::tDropConstraint: { - IR* constraint_name = NT_check(alter_list_item->left_, IRTYPE::kConstraintName); - - if (table->constraints_.empty()) { - return; - } - - Constraint* constraint = table->constraints_[rand() % table->constraints_.size()]; - instantiate_ident(constraint_name, IdentifierType::iConstraint, constraint->identifierName_); - - table->drop_constraint(constraint); - - break; - } - case TERMINAL::tAlterColumn: { - IR* column_name = NT_check(alter_list_item->left_, IRTYPE::kColumnName); - - Column* column = table->columns_[rand() % table->columns_.size()]; - instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); - - switch (alter_list_item->op_->middle_) { - case TERMINAL::tSetDefaultOpLp: { - IR* expr_root = NT_check(alter_list_item->right_, IRTYPE::kExprRoot); - - exprInstantiator_->instantiate_expr_root(expr_root, table->columns_, StmtLocation::slNotSubquery); - - break; - } - case TERMINAL::tDropDefault: { - break; - } - case TERMINAL::tSet: { - break; - } - default: { - fprintf(stderr, "ERROR: Unknown ALTER COLUMN!!!\n"); - assert(0); - } - } - - break; - } - case TERMINAL::tAlterIndex: { - IR* index_name = NT_check(alter_list_item->left_, IRTYPE::kIndexName); - - if (table->indexes_.empty()) { - return; - } - - Index* index = table->indexes_[rand() % table->indexes_.size()]; - instantiate_ident(index_name, IdentifierType::iIndex, index->identifierName_); - - break; - } - case TERMINAL::tRenameTo: { - IR* table_name = NT_check(alter_list_item->left_, IRTYPE::kTableName); - - name_t newTableName = globalStatusManger_->get_new_table_name(); - - instantiate_ident(table_name, IdentifierType::iTable, newTableName); - - table->identifierName_ = newTableName; - - break; - } - case TERMINAL::tRenameIndex: { - IR* index_name_1 = NT_check(alter_list_item->left_, IRTYPE::kIndexName); - IR* index_name_2 = NT_check(alter_list_item->right_, IRTYPE::kIndexName); - - if (table->indexes_.empty()) { - return; - } - - Index* index = table->indexes_[rand() % table->indexes_.size()]; - name_t newIndexName = globalStatusManger_->get_new_index_name(); - - instantiate_ident(index_name_1, IdentifierType::iIndex, index->identifierName_); - instantiate_ident(index_name_2, IdentifierType::iIndex, newIndexName); - - index->identifierName_ = newIndexName; - - break; - } - case TERMINAL::tRenameColumn: { - IR* column_name_1 = NT_check(alter_list_item->left_, IRTYPE::kColumnName); - IR* column_name_2 = NT_check(alter_list_item->right_, IRTYPE::kColumnName); - - Column* column = table->columns_[rand() % table->columns_.size()]; - name_t newColumnName = table->get_acce_column_name(); - - instantiate_ident(column_name_1, IdentifierType::iColumn, column->identifierName_); - instantiate_ident(column_name_2, IdentifierType::iColumn, newColumnName); - - table->column_rename(column, column->identifierName_, newColumnName); - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown alter_list_item!!!\n"); - assert(0); - } - } - - return; -} - -void Instantiator::instantiate_insert_stmt(IR* insert_stmt) { - IR* table_name = nullptr; - IR* insert_from_constructor = nullptr; - IR* opt_values_reference = nullptr; - IR* opt_insert_update_list = nullptr; - IR* update_list = nullptr; - IR* insert_query_expression = nullptr; - - IR* unknown = insert_stmt->right_->right_; - - table_name = NT_check(unknown->left_, IRTYPE::kTableName); - unknown = unknown->right_; - - switch (unknown->left_->type_) { - case IRTYPE::kInsertFromConstructor: { - insert_from_constructor = NT_check(unknown->left_, IRTYPE::kInsertFromConstructor); - unknown = unknown->right_; - - opt_values_reference = NT_check(unknown->left_, IRTYPE::kOptValuesReference); - - break; - } - case IRTYPE::kUpdateList: { - update_list = NT_check(unknown->left_, IRTYPE::kUpdateList); - unknown = unknown->right_; - - opt_values_reference = NT_check(unknown->left_, IRTYPE::kOptValuesReference); - - break; - } - case IRTYPE::kInsertQueryExpression: { - insert_query_expression = NT_check(unknown->left_, IRTYPE::kInsertQueryExpression); - break; - } - default: { - fprintf(stderr, "ERROR: Unknown Insert Stmt!!!\n"); - assert(0); - } - } - - opt_insert_update_list = NT_check(unknown->right_, IRTYPE::kOptInsertUpdateList); - - vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); - if (tables.empty()) { - return; - } - - globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - Table* chosenTable = tables[rand() % tables.size()]; - instantiate_ident(table_name, IdentifierType::iTable, chosenTable->identifierName_); - - Table* newTable = new Table(chosenTable, info); - info->add_used_table(newTable); - - int chosenColumnNumber = chosenTable->columns_.size(); - Table* tmpTable = nullptr; - - info->update_acceColumns(); - - if (insert_from_constructor != nullptr) { - bool hasOptColumn = false; - - IR* values_list = nullptr; - IR* column_list = nullptr; - - if (insert_from_constructor->right_ == nullptr) { - values_list = NT_check(insert_from_constructor->left_, IRTYPE::kValuesList); - } - else { - values_list = NT_check(insert_from_constructor->right_, IRTYPE::kValuesList); - column_list = NT_check(insert_from_constructor->left_, IRTYPE::kColumnList); - } - - if (column_list != nullptr) { - hasOptColumn = true; - - vector columnsSeq = chosenTable->get_column_seq(); - vector chosenColumns = vector(columnsSeq.begin(), columnsSeq.begin() + exprInstantiator_->get_random_integer(1, chosenTable->columns_.size())); - - chosenColumnNumber = chosenColumns.size(); - - instantiate_column_list(column_list, chosenColumns); - } - - int tmpChosenColumnNumber = chosenColumnNumber; - if (hasOptColumn == false) { - tmpChosenColumnNumber = (rand() % 20) == 0 ? 0 : chosenColumnNumber; - chosenColumnNumber = tmpChosenColumnNumber; - } - - instantiate_values_list(values_list, tmpChosenColumnNumber); - } - else if (update_list != nullptr) { - chosenColumnNumber = instantiate_update_list(update_list, nullptr); - } - else { - IR* query_expression = nullptr; - IR* column_list = nullptr; - - if (insert_query_expression->right_ == nullptr) { - query_expression = NT_check(insert_query_expression->left_, IRTYPE::kQueryExpression); - } - else { - query_expression = NT_check(insert_query_expression->right_, IRTYPE::kQueryExpression); - column_list = NT_check(insert_query_expression->left_, IRTYPE::kColumnList); - } - - if (column_list != nullptr) { - vector columnsSeq = chosenTable->get_column_seq(); - vector chosenColumns = vector(columnsSeq.begin(), columnsSeq.begin() + exprInstantiator_->get_random_integer(1, chosenTable->columns_.size())); - - chosenColumnNumber = chosenColumns.size(); - - instantiate_column_list(column_list, chosenColumns); - } - - Table* tmp = instantiate_query_expression(query_expression, StmtLocation::slNotSubquery, DEFAULTROWNUMBER, chosenColumnNumber); - delete tmp; - } - - if (opt_values_reference != nullptr && opt_values_reference->left_ != nullptr) { - if (chosenColumnNumber != 0) { - IR* tmp_table_name = NT_check(opt_values_reference->left_, IRTYPE::kTableName); - IR* opt_column_list = NT_check(opt_values_reference->right_, IRTYPE::kOptColumnList); - - name_t newTableName = globalStatusManger_->get_new_table_name(); - instantiate_ident(tmp_table_name, IdentifierType::iTable, newTableName); - - vector chosenColumns; - if (opt_insert_update_list->left_ != nullptr) { - tmpTable = new Table(newTableName, IdentifierType::iTable, info); - - for (int i = 0; i < chosenColumnNumber; i++) { - name_t newColumnName = tmpTable->get_acce_column_name(); - Column* newColumn = new Column(newColumnName, ColumnType::ctNull); - - tmpTable->add_column(newColumn); - chosenColumns.push_back(newColumnName); - } - - if (opt_column_list->left_ == nullptr) { - opt_column_list->left_ = deep_copy(IRTrim_->simple_column_list_); - opt_column_list->op_->prefix_ = TERMINAL::tOpLp; - opt_column_list->op_->middle_ = TERMINAL::tOpRp; - } - } - else { - for (int i = 0; i < chosenColumnNumber; i++) { - chosenColumns.push_back(static_cast(i)); - } - } - - if (opt_column_list->left_ != nullptr) { - IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); - instantiate_column_list(column_list, chosenColumns); - } - } - else { - deep_delete(opt_values_reference->left_); - deep_delete(opt_values_reference->right_); - - opt_values_reference->left_ = nullptr; - opt_values_reference->right_ = nullptr; - - opt_values_reference->op_->prefix_ = TERMINAL::tEmpty; - } - } - - if (opt_insert_update_list->left_ != nullptr) { - IR* tmp_update_list = NT_check(opt_insert_update_list->left_, IRTYPE::kUpdateList); - instantiate_update_list(tmp_update_list, tmpTable); - } - - if (tmpTable != nullptr) { - delete tmpTable; - } - - globalStatusManger_->pop_selectInfo(); - - return; -} -void Instantiator::instantiate_values_list(IR* values_list, int chosenColumnNumber) { - IR* curNode = values_list; - while (curNode != nullptr) { - IR* opt_values = NT_check(curNode->left_->left_, IRTYPE::kOptValues); - IR* values = opt_values->left_ == nullptr ? nullptr : NT_check(opt_values->left_, IRTYPE::kValues); - - if (chosenColumnNumber == 0 && values != nullptr) { - deep_delete(opt_values->left_); - opt_values->left_ = nullptr; - values = nullptr; - } - else if (chosenColumnNumber != 0 && values == nullptr) { - opt_values->left_ = deep_copy(IRTrim_->simple_values_); - values = opt_values->left_; - } - - if (values != nullptr) { - assert(chosenColumnNumber > 0); - instantiate_values(values, chosenColumnNumber); - } - - curNode = curNode->right_; - } - - return; -} -void Instantiator::instantiate_values(IR* values, int chosenColumnNumber) { - int count = 0; - IR* curNode = values; - while (curNode != nullptr) { - IR* expr_or_default = NT_check(curNode->left_, IRTYPE::kExprOrDefault); - IR* expr_root = expr_or_default->left_ == nullptr ? nullptr : NT_check(expr_or_default->left_, IRTYPE::kExprRoot); - - if (expr_root != nullptr) { - vector tmp; - exprInstantiator_->instantiate_expr_root(expr_root, tmp, StmtLocation::slNotSubquery); - } - - count++; - - if (count == chosenColumnNumber && curNode->right_ != nullptr) { - deep_delete(curNode->right_); - - curNode->right_ = nullptr; - curNode->op_->middle_ = TERMINAL::tEmpty; - } - else if (count < chosenColumnNumber && curNode->right_ == nullptr) { - curNode->right_ = deep_copy(IRTrim_->simple_values_); - curNode->op_->middle_ = TERMINAL::tOpComma; - } - - curNode = curNode->right_; - } - - return; -} - -void Instantiator::instantiate_update_stmt(IR* update_stmt) { - IR* opt_with_clause = nullptr; - IR* table_reference_list = nullptr; - IR* update_list = nullptr; - IR* opt_where_clause = nullptr; - IR* opt_order_clause = nullptr; - IR* opt_simple_limit = nullptr; - - IR* unknown = nullptr; - - opt_with_clause = NT_check(update_stmt->left_, IRTYPE::kOptWithClause); - unknown = update_stmt->right_->right_->right_; - - table_reference_list = NT_check(unknown->left_, IRTYPE::kTableReferenceList); - unknown = unknown->right_; - - update_list = NT_check(unknown->left_, IRTYPE::kUpdateList); - unknown = unknown->right_; - - opt_where_clause = NT_check(unknown->left_, IRTYPE::kOptWhereClause); - unknown = unknown->right_; - - opt_order_clause = NT_check(unknown->left_, IRTYPE::kOptOrderClause); - opt_simple_limit = NT_check(unknown->right_, IRTYPE::kOptSimpleLimit); - - globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (opt_with_clause->left_ != nullptr) { - IR* with_clause = NT_check(opt_with_clause->left_, IRTYPE::kWithClause); - instantiate_with_clause(with_clause); - } - - IR* curNode = table_reference_list; - while (curNode != nullptr) { - IR* table_reference = NT_check(curNode->left_, IRTYPE::kTableReference); - instantiate_table_reference(table_reference); - - curNode = curNode->right_; - } - - info->update_acceColumns(); - - if (opt_where_clause->left_ != nullptr) { - IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); - instantiate_where_clause(where_clause); - } - - if (opt_order_clause->left_ != nullptr) { - IR* order_clause = NT_check(opt_order_clause->left_, IRTYPE::kOrderClause); - instantiate_order_clause(order_clause); - } - - if (opt_simple_limit->left_ != nullptr) { - IR* iconst = NT_check(opt_simple_limit->left_, IRTYPE::kIconst); - iconst->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); - } - - instantiate_update_list(update_list, nullptr); - - globalStatusManger_->pop_selectInfo(); - - return; -} -int Instantiator::instantiate_update_list(IR* update_list, Table* table) { - int chosenColumnNumber = 0; - - vector columns; - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (info->acceColumns_.empty()) { - return 0; - } - - if (table != nullptr) { - vector tmp = vector(COLUMNNAMEMAX, 0); - - for (Column* c : table->columns_) { - tmp[c->identifierName_]++; - } - - for (Column* c : info->acceColumns_) { - Column* tmpColumn = new Column(c); - tmpColumn->parentTable_ = c->parentTable_; - - if (tmp[tmpColumn->identifierName_] != 0) { - tmpColumn->duplicated_ = ColumnStatus::csDuplication; - } - - tmp[tmpColumn->identifierName_]++; - columns.push_back(tmpColumn); - } - - for (Column* c : table->columns_) { - Column* tmpColumn = new Column(c); - tmpColumn->parentTable_ = c->parentTable_; - - if (tmp[tmpColumn->identifierName_] > 1) { - tmpColumn->duplicated_ = ColumnStatus::csDuplication; - } - - columns.push_back(tmpColumn); - } - } - - IR* curNode = update_list; - while (curNode != nullptr) { - chosenColumnNumber++; - - IR* columnref = NT_check(curNode->left_->left_, IRTYPE::kColumnref); - IR* expr_root = (curNode->left_->right_->left_ == nullptr) ? nullptr : NT_check(curNode->left_->right_->left_, IRTYPE::kExprRoot); - - Column* chosenColumn = info->acceColumns_[rand() % info->acceColumns_.size()]; - - IR* column_name = nullptr; - IR* table_name = nullptr; - - if (chosenColumn->duplicated_ == ColumnStatus::csDuplication && columnref->right_ == nullptr) { - IR* tmp1 = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* tmp2 = new IR(IRTYPE::kTableName, OP0(), tmp1, nullptr); - - columnref->right_ = columnref->left_; - columnref->left_ = tmp2; - columnref->op_->middle_ = TERMINAL::tOpDot; - } - - if (columnref->right_ != nullptr) { - table_name = NT_check(columnref->left_, IRTYPE::kTableName); - column_name = NT_check(columnref->right_, IRTYPE::kColumnName); - } - else { - column_name = NT_check(columnref->left_, IRTYPE::kColumnName); - } - - instantiate_ident(column_name, IdentifierType::iColumn, chosenColumn->identifierName_); - if (table_name != nullptr) { - instantiate_ident(table_name, IdentifierType::iTable, chosenColumn->parentTable_->identifierName_); - } - - if (expr_root != nullptr) { - if (table != nullptr) { - exprInstantiator_->instantiate_expr_root(expr_root, columns, StmtLocation::slNotSubquery); - } - else { - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slNotSubquery); - } - } - - curNode = curNode->right_; - } - - for (Column* c : columns) { - delete c; - } - - return chosenColumnNumber; -} - -void Instantiator::instantiate_delete_stmt(IR* delete_stmt) { - IR* opt_with_clause = nullptr; - IR* table_name = nullptr; - IR* opt_alias = nullptr; - IR* opt_where_clause = nullptr; - IR* opt_order_clause = nullptr; - IR* opt_simple_limit = nullptr; - IR* table_list = nullptr; - IR* table_reference_list = nullptr; - - IR* unknown = nullptr; - - opt_with_clause = NT_check(delete_stmt->left_, IRTYPE::kOptWithClause); - unknown = delete_stmt->right_->right_; - - if (unknown->left_->type_ == IRTYPE::kTableName) { - table_name = NT_check(unknown->left_, IRTYPE::kTableName); - unknown = unknown->right_; - - opt_alias = NT_check(unknown->left_, IRTYPE::kOptAlias); - unknown = unknown->right_; - - opt_where_clause = NT_check(unknown->left_, IRTYPE::kOptWhereClause); - unknown = unknown->right_; - - opt_order_clause = NT_check(unknown->left_, IRTYPE::kOptOrderClause); - opt_simple_limit = NT_check(unknown->right_, IRTYPE::kOptSimpleLimit); - } - else { - table_list = NT_check(unknown->left_, IRTYPE::kTableList); - unknown = unknown->right_; - - table_reference_list = NT_check(unknown->left_, IRTYPE::kTableReferenceList); - opt_where_clause = NT_check(unknown->right_, IRTYPE::kOptWhereClause); - } - - globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (table_name != nullptr) { - if (opt_with_clause->left_ != nullptr) { - deep_delete(opt_with_clause->left_); - opt_with_clause->left_ = nullptr; - } - - vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); - if (tables.empty()) { - globalStatusManger_->pop_selectInfo(); - return; - } - - Table* chosenTable = tables[rand() % tables.size()]; - Table* newTable = new Table(chosenTable, info); - info->add_used_table(newTable); - - instantiate_ident(table_name, IdentifierType::iTable, newTable->identifierName_); - - if (opt_alias->left_ != nullptr) { - IR* alias = NT_check(opt_alias->left_, IRTYPE::kAlias); - name_t newName = globalStatusManger_->get_new_table_name(); - - instantiate_ident(alias, IdentifierType::iTable, newName); - - newTable->identifierName_ = newName; - } - - info->update_acceColumns(); - - if (opt_where_clause->left_ != nullptr) { - IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); - instantiate_where_clause(where_clause); - } - - if (opt_order_clause->left_ != nullptr) { - IR* order_clause = NT_check(opt_order_clause->left_, IRTYPE::kOrderClause); - instantiate_order_clause(order_clause); - } - - if (opt_simple_limit->left_ != nullptr) { - IR* iconst = NT_check(opt_simple_limit->left_, IRTYPE::kIconst); - iconst->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); - } - } - else if (table_list != nullptr) { - if (opt_with_clause->left_ != nullptr) { - IR* with_clause = NT_check(opt_with_clause->left_, IRTYPE::kWithClause); - instantiate_with_clause(with_clause); - } - - IR* curNode = table_reference_list; - while (curNode != nullptr) { - IR* table_reference = NT_check(curNode->left_, IRTYPE::kTableReference); - instantiate_table_reference(table_reference); - - curNode = curNode->right_; - } - - info->update_acceColumns(); - - vector tables = info->usedTables_; - assert(!tables.empty()); - - curNode = table_list; - while (curNode != nullptr) { - IR* table_name = NT_check(curNode->left_, IRTYPE::kTableName); - - int tmp = rand() % tables.size(); - Table* table = tables[tmp]; - tables.erase(tables.begin() + tmp); - - instantiate_ident(table_name, table->identifierType_, table->identifierName_); - - if (tables.empty() && curNode->right_ != nullptr) { - deep_delete(curNode->right_); - curNode->right_ = nullptr; - curNode->op_->middle_ = TERMINAL::tEmpty; - } - - curNode = curNode->right_; - } - - if (opt_where_clause->left_ != nullptr) { - IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); - instantiate_where_clause(where_clause); - } - } - else { - fprintf(stderr, "ERROR: Incorrect Delete Statement!!!\n"); - assert(0); - } - - globalStatusManger_->pop_selectInfo(); - - return; -} - -void Instantiator::instantiate_drop_table_or_view_stmt(IR* drop_table_stmt, IdentifierType type) { - bool existFlag = false; - - IR* if_exists = NT_check(drop_table_stmt->left_, IRTYPE::kIfExists); - IR* table_list = NT_check(drop_table_stmt->right_, IRTYPE::kTableList); - - vector tables = globalStatusManger_->get_acce_table(type); - if (tables.empty()) { - if_exists->op_->prefix_ = TERMINAL::tIfExists; - } - - if (if_exists->op_->prefix_ == TERMINAL::tIfExists) { - existFlag = true; - } - - name_t nextTableName = UNREFERENCE; - if (type == IdentifierType::iTable) { - nextTableName = globalStatusManger_->get_new_table_name(); - } - else if (type == IdentifierType::iView) { - nextTableName = globalStatusManger_->get_new_view_name(); - } - else { - fprintf(stderr, "ERROR: IdentifierType isn't iTable or iView!!!\n"); - assert(0); - } - - IR* curNode = table_list; - while (curNode != nullptr) { - name_t tmpTableName = UNREFERENCE; - IR* table_name = NT_check(curNode->left_, IRTYPE::kTableName); - - if (existFlag == true && (rand() % 2 == 0 || tables.empty())) { - tmpTableName = exprInstantiator_->get_random_integer(nextTableName, UCHAR_MAX); - } - else { - int tmp = rand() % tables.size(); - Table* tmpTable = tables[tmp]; - - tmpTableName = tmpTable->identifierName_; - - tables.erase(tables.begin() + tmp); - globalStatusManger_->drop_table(tmpTable); - } - - instantiate_ident(table_name, type, tmpTableName); - - if (existFlag == false && tables.empty() && curNode->right_ != nullptr) { - deep_delete(curNode->right_); - curNode->right_ = nullptr; - curNode->op_->middle_ = TERMINAL::tEmpty; - } - - curNode = curNode->right_; - } - - return; -} - -void Instantiator::instantiate_drop_index_stmt(IR* drop_index_stmt) { - IR* index_name = NT_check(drop_index_stmt->left_, IRTYPE::kIndexName); - IR* table_name = NT_check(drop_index_stmt->right_, IRTYPE::kTableName); - - vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); - if (tables.empty()) { - return; - } - - Table* table = nullptr; - for (Table* t : tables) { - if (t->indexes_.empty()) { - continue; - } - - table = t; - break; - } - - if (table == nullptr) { - return; - } - - Index* index = table->indexes_[rand() % table->indexes_.size()]; - - instantiate_ident(index_name, IdentifierType::iIndex, index->identifierName_); - instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); - - table->drop_index(index); - - return; -} - -void Instantiator::instantiate_create_index_stmt(IR* create_index_stmt) { - IR* index_name = nullptr; - IR* table_name = nullptr; - IR* key_list_with_expression = nullptr; - - IR* unknown = create_index_stmt->right_; - - index_name = NT_check(unknown->left_, IRTYPE::kIndexName); - unknown = unknown->right_; - - table_name = NT_check(unknown->left_, IRTYPE::kTableName); - key_list_with_expression = NT_check(unknown->right_, IRTYPE::kKeyListWithExpression); - - vector tables = globalStatusManger_->get_acce_table(IdentifierType::iTable); - if (tables.empty()) { - return; - } - - Table* table = tables[rand() % tables.size()]; - - name_t newIndexName = globalStatusManger_->get_new_index_name(); - Index* newIndex = new Index(newIndexName); - - instantiate_ident(index_name, IdentifierType::iIndex, newIndex->identifierName_); - instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); - - newIndex->columns_ = instantiate_key_list_with_expression(key_list_with_expression, table, ConstraintType::ctNull); - - table->add_index(newIndex); - - return; -} - -void Instantiator::instantiate_create_view_stmt(IR* create_view_stmt) { - IR* opt_or_replace = nullptr; - IR* view_name = nullptr; - IR* opt_column_list = nullptr; - IR* query_expression = nullptr; - - IR* unknown = nullptr; - - opt_or_replace = NT_check(create_view_stmt->left_, IRTYPE::kOptOrReplace); - unknown = create_view_stmt->right_->right_; - - view_name = NT_check(unknown->left_, IRTYPE::kViewName); - unknown = unknown->right_; - - opt_column_list = NT_check(unknown->left_, IRTYPE::kOptColumnList); - query_expression = NT_check(unknown->right_, IRTYPE::kQueryExpression); - - name_t newViewName = globalStatusManger_->get_new_view_name(); - if (opt_or_replace->op_->prefix_ == TERMINAL::tOrReplace) { - newViewName = (newViewName != 0 && (rand() % 2) == 0) ? (rand() % newViewName) : newViewName; - globalStatusManger_->drop_table(newViewName, IdentifierType::iView); - } - - instantiate_ident(view_name, IdentifierType::iView, newViewName); - - Table* view = instantiate_query_expression(query_expression, StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - - view->identifierName_ = newViewName; - view->identifierType_ = IdentifierType::iView; - - if (opt_column_list->left_ != nullptr) { - IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); - - for (Column* column : view->columns_) { - view->column_rename(column, column->identifierName_, view->get_acce_column_name()); - } - - instantiate_column_list(column_list, view->columns_); - } - - assert(globalStatusManger_->add_table(view)); - - return; -} - -void Instantiator::instantiate_create_table_stmt(IR* create_table_stmt) { - Table* res = nullptr; - - IR* opt_temporary = nullptr; - IR* opt_if_not_exists = nullptr; - IR* table_name = nullptr; - IR* table_element_list = nullptr; - IR* duplicate_as_qe = nullptr; - IR* opt_duplicate_as_qe = nullptr; - - IR* unknown = nullptr; - - opt_temporary = NT_check(create_table_stmt->left_, IRTYPE::kOptTemporary); - unknown = create_table_stmt->right_; - - opt_if_not_exists = NT_check(unknown->left_, IRTYPE::kOptIfNotExists); - unknown = unknown->right_; - - table_name = NT_check(unknown->left_, IRTYPE::kTableName); - unknown = unknown->right_; - - if (unknown->type_ == IRTYPE::kDuplicateAsQe) { - duplicate_as_qe = NT_check(unknown, IRTYPE::kDuplicateAsQe); - } - else { - table_element_list = NT_check(unknown->left_, IRTYPE::kTableElementList); - opt_duplicate_as_qe = NT_check(unknown->right_, IRTYPE::kOptDuplicateAsQe); - - if (opt_duplicate_as_qe->left_ != nullptr) { - duplicate_as_qe = NT_check(opt_duplicate_as_qe->left_, IRTYPE::kDuplicateAsQe); - } - } - - name_t newTableName = globalStatusManger_->get_new_table_name(); - instantiate_ident(table_name, IdentifierType::iTable, newTableName); - - if (table_element_list != nullptr) { - res = new Table(newTableName, IdentifierType::iTable, nullptr); - instantiate_table_element_list(table_element_list, res); - } - - if (duplicate_as_qe != nullptr) { - IR* query_expression = nullptr; - - if (duplicate_as_qe->left_->type_ == IRTYPE::kQueryExpression) { - query_expression = NT_check(duplicate_as_qe->left_, IRTYPE::kQueryExpression); - } - else { - query_expression = NT_check(duplicate_as_qe->right_, IRTYPE::kQueryExpression); - } - - Table* tmpTable = instantiate_query_expression(query_expression, StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - - if (res == nullptr) { - res = tmpTable; - } - else { - for (Column* c : tmpTable->columns_) { - res->add_column(new Column(c), nullptr); - } - - delete tmpTable; - } - - res->identifierName_ = newTableName; - } - - if (opt_temporary->op_->prefix_ == TERMINAL::tTemporary) { - res->isTemporary_ = true; - } - - assert(globalStatusManger_->add_table(res)); - - return; -} -void Instantiator::instantiate_table_element_list(IR* table_element_list, Table* table) { - map> columnWithColumnAttributes; - - int column_def_count = 0; - IR* curNode = table_element_list; - while (curNode != nullptr) { - IR* table_element = NT_check(curNode->left_, IRTYPE::kTableElement); - - if (table_element->left_->type_ == IRTYPE::kColumnDef) { - column_def_count++; - } - - curNode = curNode->right_; - } - - if (table->columns_.empty() && column_def_count == 0) { - deep_delete(table_element_list->left_); - table_element_list->left_ = deep_copy(IRTrim_->simple_table_element_); - } - - curNode = table_element_list; - vector tableConstraintDefs; - while (curNode != nullptr) { - IR* table_element = curNode->left_; - - if (table_element->left_->type_ == IRTYPE::kColumnDef) { - pair> tmp = instantiate_column_def(NT_check(table_element->left_, IRTYPE::kColumnDef), table); - columnWithColumnAttributes[tmp.first] = tmp.second; - } - else { - tableConstraintDefs.push_back(NT_check(table_element->left_, IRTYPE::kTableConstraintDef)); - } - - curNode = curNode->right_; - } - - assert(!table->columns_.empty()); - - for (auto& it : columnWithColumnAttributes) { - for (IR* column_attribute : it.second) { - instantiate_column_attribute(column_attribute, it.first, table); - } - } - - vector waitForDelete; - for (IR* tmp : tableConstraintDefs) { - bool flag = false; - - if (tmp->left_->type_ == IRTYPE::kOptIndexName) { - flag = instantiate_table_constraint_def_index(tmp, table); - } - else if (tmp->right_->type_ == IRTYPE::kCheckConstraint) { - flag = instantiate_table_constraint_def_check(tmp, table); - } - else if (tmp->op_->middle_ == TERMINAL::tForeignKey) { - flag = instantiate_table_constraint_def_foreign_key(tmp, table); - } - else { - flag = instantiate_table_constraint_def_key(tmp, table); - } - - if (flag == false) { - waitForDelete.push_back(tmp); - } - } - - curNode = table_element_list; - IR* preNode = curNode; - while (curNode != nullptr && !waitForDelete.empty()) { - IR* table_element = curNode->left_; - - auto it = find(waitForDelete.begin(), waitForDelete.end(), table_element->left_); - if (it != waitForDelete.end()) { - if (curNode->right_ == nullptr) { - deep_delete(preNode->right_); - preNode->right_ = nullptr; - preNode->op_->middle_ = TERMINAL::tEmpty; - - curNode = preNode; - - waitForDelete.erase(it); - } - else { - IR* tmp = curNode->right_; - - deep_delete(curNode->left_); - curNode->left_ = tmp->left_; - curNode->right_ = tmp->right_; - curNode->op_->middle_ = tmp->op_->middle_; - - tmp->left_ = nullptr; - tmp->right_ = nullptr; - deep_delete(tmp); - - waitForDelete.erase(it); - - continue; - } - } - - preNode = curNode; - curNode = curNode->right_; - } - - assert(waitForDelete.empty()); - - return; -} -pair> Instantiator::instantiate_column_def(IR* column_def, Table* table) { - vector res; - - IR* column_name = NT_check(column_def->left_, IRTYPE::kColumnName); - IR* data_type = NT_check(column_def->right_->left_, IRTYPE::kDataType); - IR* opt_column_attribute_list = NT_check(column_def->right_->right_, IRTYPE::kOptColumnAttributeList); - - name_t columnName = table->get_acce_column_name(); - ColumnType type = instantiate_data_type(data_type); - - Column* column = new Column(columnName, type); - instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); - - if (opt_column_attribute_list->left_ != nullptr) { - IR* column_attribute_list = NT_check(opt_column_attribute_list->left_, IRTYPE::kColumnAttributeList); - - while (column_attribute_list != nullptr) { - res.push_back(NT_check(column_attribute_list->left_, IRTYPE::kColumnAttribute)); - column_attribute_list = column_attribute_list->right_; - } - } - - table->add_column(column); - - return { column, res }; -} -ColumnType Instantiator::instantiate_data_type(IR* data_type) { - ColumnType res = ColumnType::ctNull; - - switch (data_type->left_->type_) { - case IRTYPE::kNumberType: { - IR* number_type = NT_check(data_type->left_, IRTYPE::kNumberType); - - IR* type = number_type->left_; - IR* precision = nullptr; - IR* float_options = nullptr; - - if (type->type_ == IRTYPE::kRealType) { - IR* opt_precision = NT_check(number_type->right_->left_, IRTYPE::kOptPrecision); - precision = (opt_precision->left_ == nullptr) ? nullptr : NT_check(opt_precision->left_, IRTYPE::kPrecision); - } - else if (type->type_ == IRTYPE::kNumericType) { - float_options = NT_check(number_type->right_->left_, IRTYPE::kFloatOptions); - } - - res = Column::typeTranslation_[type->op_->prefix_]; - - if (float_options != nullptr && float_options->left_ != nullptr) { - if (float_options->left_->type_ == IRTYPE::kPrecision) { - precision = NT_check(float_options->left_, IRTYPE::kPrecision); - } - else { - IR* field_length = NT_check(float_options->left_, IRTYPE::kFieldLength); - IR* iconst = NT_check(field_length->left_, IRTYPE::kIconst); - - int v1 = exprInstantiator_->get_random_integer(0, 53); - iconst->long_val_ = v1; - } - } - - if (precision != nullptr) { - IR* iconst_1 = NT_check(precision->left_, IRTYPE::kIconst); - IR* iconst_2 = NT_check(precision->right_, IRTYPE::kIconst); - - int v1 = exprInstantiator_->get_random_integer(1, 255); - int v2 = exprInstantiator_->get_random_float(0, min(v1, 30)); - - iconst_1->long_val_ = v1; - iconst_2->long_val_ = v2; - } - - break; - } - case IRTYPE::kBoolType: { - res = Column::typeTranslation_[data_type->left_->op_->prefix_]; - break; - } - case IRTYPE::kStringType: { - IR* string_type = NT_check(data_type->left_, IRTYPE::kStringType); - - IR* field_length = nullptr; - if (string_type->left_ != nullptr) { - field_length = (string_type->left_->type_ == IRTYPE::kFieldLength) ? NT_check(string_type->left_, IRTYPE::kFieldLength) : string_type->left_->left_; - } - - res = Column::typeTranslation_[string_type->op_->prefix_]; - - if (field_length != nullptr) { - IR* iconst = NT_check(field_length->left_, IRTYPE::kIconst); - - int v1 = exprInstantiator_->get_random_integer(32, 255); - iconst->long_val_ = v1; - } - - break; - } - default: { - fprintf(stderr, "Unknown Data Type!!!\n"); - assert(0); - } - } - - return res; -} -void Instantiator::instantiate_column_attribute(IR* column_attribute, Column* column, Table* table) { - switch (column_attribute->left_->type_) { - case IRTYPE::kNotNull: { - column->notNull_ = true; - break; - } - case IRTYPE::kDefaultAttribute: { - IR* expr_root = NT_check(column_attribute->left_->left_, IRTYPE::kExprRoot); - exprInstantiator_->instantiate_expr_root(expr_root, table->columns_, StmtLocation::slNotSubquery); - - column->hasDefault_ = true; - - break; - } - case IRTYPE::kVisibility: { - column->isVisible_ = (column_attribute->left_->op_->prefix_ == TERMINAL::tVisible) ? true : false; - break; - } - default: { - fprintf(stderr, "Unknown Column Attribute!!!\n"); - assert(0); - } - } - - return; -} -map Instantiator::instantiate_key_list_with_expression(IR* key_list_with_expression, Table* table, ConstraintType type) { - map res; - - IR* curNode = key_list_with_expression; - while (curNode != nullptr) { - IR* key_part_with_expression = NT_check(curNode->left_, IRTYPE::kKeyPartWithExpression); - - if (type == ConstraintType::ctPrimaryKey && key_part_with_expression->left_->type_ != IRTYPE::kKeyPart) { - deep_delete(key_part_with_expression->left_); - key_part_with_expression->left_ = deep_copy(IRTrim_->simple_key_part_); - } - - if (key_part_with_expression->left_->type_ == IRTYPE::kKeyPart) { - IR* key_part = NT_check(key_part_with_expression->left_, IRTYPE::kKeyPart); - IR* iconst = nullptr; - - Column* columnChosen = table->get_column(); - instantiate_ident(NT_check(key_part->left_, IRTYPE::kColumnName), IdentifierType::iColumn, columnChosen->identifierName_); - - if (res.find(columnChosen) == res.end()) { - res[columnChosen] = IndexType::itNormal; - } - - if (key_part->right_->type_ != IRTYPE::kOptOrderingDirection) { - if (Column::typeToBasicType_[columnChosen->columnType_] != ColumnBasicType::ctString) { - deep_delete(key_part->right_); - key_part->right_ = new IR(IRTYPE::kOptOrderingDirection, OP0(), nullptr, nullptr); - } - else { - iconst = NT_check(key_part->right_->left_, IRTYPE::kIconst); - } - } - - if (iconst != nullptr) { - int v1 = exprInstantiator_->get_random_integer(1, 32); - iconst->long_val_ = v1; - } - } - else { - IR* expr_root = NT_check(key_part_with_expression->left_, IRTYPE::kExprRoot); - exprInstantiator_->instantiate_expr_root(expr_root, table->columns_, StmtLocation::slNotSubquery); - - for (Column* column : exprInstantiator_->usedColumnsBuffer_) { - res[column] = IndexType::itFunctional; - } - } - - curNode = curNode->right_; - } - - return res; -} -bool Instantiator::instantiate_table_constraint_def_index(IR* table_constraint_def, Table* table) { - IR* opt_index_name = NT_check(table_constraint_def->left_, IRTYPE::kOptIndexName); - IR* key_list_with_expression = NT_check(table_constraint_def->right_, IRTYPE::kKeyListWithExpression); - - if (opt_index_name->left_ == nullptr) { - opt_index_name->left_ = deep_copy(IRTrim_->simple_index_name_); - } - - name_t newIndexName = globalStatusManger_->get_new_index_name(); - Index* newIndex = new Index(newIndexName); - instantiate_ident(NT_check(opt_index_name->left_, IRTYPE::kIndexName), IdentifierType::iIndex, newIndex->identifierName_); - - newIndex->columns_ = instantiate_key_list_with_expression(key_list_with_expression, table, ConstraintType::ctNull); - - table->add_index(newIndex); - - return true; -} -bool Instantiator::instantiate_table_constraint_def_key(IR* table_constraint_def, Table* table) { - ConstraintType type = ConstraintType::ctNull; - - IR* opt_constraint_name = nullptr; - IR* constraint_key_type = nullptr; - IR* opt_index_name = nullptr; - IR* key_list_with_expression = nullptr; - - IR* unknown = nullptr; - - opt_constraint_name = NT_check(table_constraint_def->left_, IRTYPE::kOptConstraintName); - unknown = table_constraint_def->right_; - - constraint_key_type = NT_check(unknown->left_, IRTYPE::kConstraintKeyType); - unknown = unknown->right_; - - opt_index_name = NT_check(unknown->left_, IRTYPE::kOptIndexName); - key_list_with_expression = NT_check(unknown->right_, IRTYPE::kKeyListWithExpression); - - if (opt_constraint_name->left_ == nullptr) { - opt_constraint_name->left_ = deep_copy(IRTrim_->simple_constraint_name_); - opt_constraint_name->op_->prefix_ = TERMINAL::tConstraint; - } - - if (opt_index_name->left_ == nullptr) { - opt_index_name->left_ = deep_copy(IRTrim_->simple_index_name_); - } - - if (table->hasPrimaryKey_ == true) { - if (constraint_key_type->op_->prefix_ == TERMINAL::tPrimaryKey); { - return false; - } - - type = ConstraintType::ctUnique; - } - else { - type = (constraint_key_type->op_->prefix_ == TERMINAL::tPrimaryKey) ? ConstraintType::ctPrimaryKey : ConstraintType::ctUnique; - if (type == ConstraintType::ctPrimaryKey) { - table->hasPrimaryKey_ = true; - } - } - - name_t newConstraintName = globalStatusManger_->get_new_constraint_name(); - name_t newIndexName = globalStatusManger_->get_new_index_name(); - - Constraint* newConstraint = new Constraint(newConstraintName, type); - Index* newIndex = new Index(newIndexName); - - instantiate_ident(NT_check(opt_constraint_name->left_, IRTYPE::kConstraintName), IdentifierType::iConstraint, newConstraint->identifierName_); - instantiate_ident(NT_check(opt_index_name->left_, IRTYPE::kIndexName), IdentifierType::iIndex, newIndex->identifierName_); - - newConstraint->columns_ = instantiate_key_list_with_expression(key_list_with_expression, table, type); - newIndex->columns_ = newConstraint->columns_; - - table->add_constraint(newConstraint, newIndex); - - return true; -} -bool Instantiator::instantiate_table_constraint_def_check(IR* table_constraint_def, Table* table) { - IR* opt_constraint_name = NT_check(table_constraint_def->left_, IRTYPE::kOptConstraintName); - IR* check_constraint = NT_check(table_constraint_def->right_, IRTYPE::kCheckConstraint); - - if (opt_constraint_name->left_ == nullptr) { - opt_constraint_name->left_ = deep_copy(IRTrim_->simple_constraint_name_); - opt_constraint_name->op_->prefix_ = TERMINAL::tConstraint; - } - - name_t newConstraintName = globalStatusManger_->get_new_constraint_name(); - Constraint* newConstraint = new Constraint(newConstraintName, ConstraintType::ctCheck); - instantiate_ident(NT_check(opt_constraint_name->left_, IRTYPE::kConstraintName), IdentifierType::iConstraint, newConstraint->identifierName_); - - exprInstantiator_->instantiate_expr_root(NT_check(check_constraint->left_, IRTYPE::kExprRoot), table->columns_, StmtLocation::slNotSubquery); - for (Column* column : exprInstantiator_->usedColumnsBuffer_) { - newConstraint->columns_[column] = IndexType::itFunctional; - } - - table->add_constraint(newConstraint); - - return true; -} -bool Instantiator::instantiate_table_constraint_def_foreign_key(IR* table_constraint_def, Table* table) { - IR* opt_constraint_name = nullptr; - IR* opt_index_name = nullptr; - IR* key_list = nullptr; - IR* references = nullptr; - IR* table_name = nullptr; - IR* column_list = nullptr; - - IR* unknown = nullptr; - - opt_constraint_name = NT_check(table_constraint_def->left_, IRTYPE::kOptConstraintName); - unknown = table_constraint_def->right_; - - opt_index_name = NT_check(unknown->left_, IRTYPE::kOptIndexName); - unknown = unknown->right_; - - key_list = NT_check(unknown->left_, IRTYPE::kKeyList); - references = NT_check(unknown->right_, IRTYPE::kReferences); - - table_name = NT_check(references->left_, IRTYPE::kTableName); - column_list = NT_check(references->right_->left_, IRTYPE::kColumnList); - - vector curTableColumn; - vector otherTableColumn; - if (check_foreign_key(table, curTableColumn, otherTableColumn) == false) { - return false; - } - - assert(!curTableColumn.empty() && curTableColumn.size() == otherTableColumn.size()); - - if (opt_constraint_name->left_ == nullptr) { - opt_constraint_name->left_ = deep_copy(IRTrim_->simple_constraint_name_); - opt_constraint_name->op_->prefix_ = TERMINAL::tConstraint; - } - - if (opt_index_name->left_ == nullptr) { - opt_index_name->left_ = deep_copy(IRTrim_->simple_index_name_); - } - - name_t newConstraintName = globalStatusManger_->get_new_constraint_name(); - name_t newIndexName = globalStatusManger_->get_new_index_name(); - - Constraint* newConstraint = new Constraint(newConstraintName, ConstraintType::ctForeignKey); - - IR* constraint_name = NT_check(opt_constraint_name->left_, IRTYPE::kConstraintName); - IR* index_name = NT_check(opt_index_name->left_, IRTYPE::kIndexName); - - instantiate_ident(constraint_name, IdentifierType::iConstraint, newConstraint->identifierName_); - instantiate_ident(index_name, IdentifierType::iIndex, newIndexName); - - instantiate_ident(table_name, IdentifierType::iTable, otherTableColumn[0]->parentTable_->identifierName_); - - instantiate_key_list(key_list, curTableColumn); - instantiate_column_list(column_list, otherTableColumn); - - for (int i = 0; i < curTableColumn.size(); i++) { - newConstraint->refToOtherColumns_[curTableColumn[i]].push_back(otherTableColumn[i]); - } - - table->add_constraint(newConstraint); - - return true; -} - -void Instantiator::instantiate_select_stmt(IR* select_stmt) { - globalStatusManger_->push_selectInfo(StmtLocation::slNotSubquery, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - - Table* t = instantiate_query_expression(NT_check(select_stmt->left_, IRTYPE::kQueryExpression)); - - globalStatusManger_->pop_selectInfo(); - delete t; - - return; -} -Table* Instantiator::instantiate_query_expression(IR* query_expression, StmtLocation location, int rowNumber, int columnNumber) { - globalStatusManger_->push_selectInfo(location, rowNumber, columnNumber); - - Table* res = instantiate_query_expression(NT_check(query_expression, IRTYPE::kQueryExpression)); - globalStatusManger_->pop_selectInfo(); - - res->inSelectStmtInfo_ = globalStatusManger_->get_cur_selectInfo(); - - return res; -} -Table* Instantiator::instantiate_query_expression(IR* query_expression) { - Table* res = nullptr; - - IR* with_clause = nullptr; - IR* query_expression_body = nullptr; - IR* opt_order_clause = nullptr; - IR* opt_limit_clause = nullptr; - - IR* unknown = nullptr; - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (query_expression->left_->type_ == IRTYPE::kQueryExpressionBody) { - query_expression_body = NT_check(query_expression->left_, IRTYPE::kQueryExpressionBody); - unknown = query_expression->right_; - } - else { - with_clause = NT_check(query_expression->left_, IRTYPE::kWithClause); - - unknown = query_expression->right_; - query_expression_body = NT_check(unknown->left_, IRTYPE::kQueryExpressionBody); - - unknown = unknown->right_; - } - - opt_order_clause = NT_check(unknown->left_, IRTYPE::kOptOrderClause); - opt_limit_clause = NT_check(unknown->right_, IRTYPE::kOptLimitClause); - - if (with_clause != nullptr) { - instantiate_with_clause(with_clause); - } - - switch (query_expression_body->left_->type_) { - case IRTYPE::kQueryPrimary: { - res = instantiate_query_primary(NT_check(query_expression_body->left_, IRTYPE::kQueryPrimary)); - break; - } - case IRTYPE::kQueryExpressionParens: { - IR* query_expression_parens = NT_check(query_expression_body->left_, IRTYPE::kQueryExpressionParens); - while (query_expression_parens->left_->type_ == IRTYPE::kQueryExpressionParens) { - query_expression_parens = NT_check(query_expression_parens->left_, IRTYPE::kQueryExpressionParens); - } - - res = instantiate_query_expression(NT_check(query_expression_parens->left_, IRTYPE::kQueryExpression)); - - break; - } - case IRTYPE::kQueryExpressionBody: { - res = instanitate_union(query_expression_body); - break; - } - default: { - fprintf(stderr, "ERROR: Unknown query_expression_body->left_->type_: %d\n", static_cast(query_expression_body->left_->type_)); - assert(0); - } - } - - assert(info->usedTables_.empty()); - - if (opt_order_clause->left_ != nullptr) { - IR* order_clause = NT_check(opt_order_clause->left_, IRTYPE::kOrderClause); - - vector usedTables = { res }; - vector duplicationInfo = vector(COLUMNNAMEMAX, 0); - info->update_acceColumns(usedTables, duplicationInfo); - - instantiate_order_clause(order_clause); - - info->acceColumns_.clear(); - } - - if (info->has_row_limit() && opt_limit_clause->left_ == nullptr) { - opt_limit_clause->left_ = deep_copy(IRTrim_->simple_limit_); - } - - if (opt_limit_clause->left_ != nullptr) { - IR* limit_clause = NT_check(opt_limit_clause->left_, IRTYPE::kLimitClause); - instantiate_limit_clause(limit_clause); - } - - return res; -} -Table* Instantiator::instantiate_query_primary(IR* query_primary) { - Table* res = nullptr; - - IR* query_specification = nullptr; - - IR* opt_select_options = nullptr; - IR* select_item_list = nullptr; - IR* opt_from_clause = nullptr; - IR* opt_where_clause = nullptr; - IR* opt_group_clause = nullptr; - IR* opt_having_clause = nullptr; - IR* opt_window_clause = nullptr; - - IR* unknown = nullptr; - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - info->clear_local_info(); - - query_specification = NT_check(query_primary->left_, IRTYPE::kQuerySpecification); - - opt_select_options = NT_check(query_specification->left_, IRTYPE::kOptSelectOptions); - unknown = query_specification->right_; - - select_item_list = NT_check(unknown->left_, IRTYPE::kSelectItemList); - unknown = unknown->right_; - - opt_from_clause = NT_check(unknown->left_, IRTYPE::kOptFromClause); - unknown = unknown->right_; - - opt_where_clause = NT_check(unknown->left_, IRTYPE::kOptWhereClause); - unknown = unknown->right_; - - opt_group_clause = NT_check(unknown->left_, IRTYPE::kOptGroupClause); - unknown = unknown->right_; - - opt_having_clause = NT_check(unknown->left_, IRTYPE::kOptHavingClause); - opt_window_clause = NT_check(unknown->right_, IRTYPE::kOptWindowClause); - - if (opt_from_clause->left_) { - int acceTableNumber = globalStatusManger_->get_acce_table_number(); - - if (acceTableNumber == 0) { - deep_delete(opt_from_clause->left_); - opt_from_clause->left_ = nullptr; - } - else { - IR* from_clause = NT_check(opt_from_clause->left_, IRTYPE::kFromClause); - instantiate_from_clause(from_clause); - } - } - - info->update_acceColumns(); - - if (opt_where_clause->left_ != nullptr) { - IR* where_clause = NT_check(opt_where_clause->left_, IRTYPE::kWhereClause); - instantiate_where_clause(where_clause); - } - - if (opt_having_clause->left_ != nullptr) { - instantiate_having_clause(opt_having_clause); - } - - if (opt_window_clause->left_ != nullptr) { - instantiate_window_clause(opt_window_clause); - } - - res = instantiate_select_item_list(select_item_list); - - if (info->hasAggregate && !info->usedInnerColumns_.empty() && opt_group_clause->left_ == nullptr) { - IR* olap_opt = new IR(IRTYPE::kOlapOpt, OP0(), nullptr, nullptr); - IR* expr_root_list = deep_copy(IRTrim_->simple_expr_root_list_); - - opt_group_clause->left_ = expr_root_list; - opt_group_clause->right_ = olap_opt; - opt_group_clause->op_->prefix_ = TERMINAL::tGroupBy; - } - - if (opt_group_clause->left_ != nullptr) { - instantiate_group_clause(opt_group_clause); - } - - info->clear_local_info(); - - return res; -} -Table* Instantiator::instanitate_union(IR* query_expression_body) { - Table* res = nullptr; - - IR* query_expression_body_1 = nullptr; - IR* query_expression_body_2 = nullptr; - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - StmtLocation oldLocation = info->location_; - - stack stk; - vector queue; - - query_expression_body_1 = NT_check(query_expression_body->left_, IRTYPE::kQueryExpressionBody); - query_expression_body_2 = NT_check(query_expression_body->right_->right_, IRTYPE::kQueryExpressionBody); - - stk.push(query_expression_body_2); - stk.push(query_expression_body_1); - - while (!stk.empty()) { - IR* curIR = stk.top(); - stk.pop(); - - switch (curIR->left_->type_) { - case IRTYPE::kQueryPrimary: { - IR* query_primary = NT_check(curIR->left_, IRTYPE::kQueryPrimary); - queue.push_back(query_primary); - - break; - } - case IRTYPE::kQueryExpressionParens: { - IR* query_expression_parens = NT_check(curIR->left_, IRTYPE::kQueryExpressionParens); - queue.push_back(query_expression_parens); - - break; - } - case IRTYPE::kQueryExpressionBody: { - IR* t_query_expression_body_1 = NT_check(curIR->left_, IRTYPE::kQueryExpressionBody); - IR* t_query_expression_body_2 = NT_check(curIR->right_->right_, IRTYPE::kQueryExpressionBody); - - stk.push(t_query_expression_body_2); - stk.push(t_query_expression_body_1); - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown query_expression_body->left_->type_: %d\n", static_cast(curIR->left_->type_)); - assert(0); - } - } - } - - assert(queue.size() >= 2); - - for (int i = 0; i < queue.size(); i++) { - if (i == 0 && (oldLocation == StmtLocation::slRecursiveCTE || oldLocation == StmtLocation::slRecursivePart1)) { - info->location_ = StmtLocation::slRecursivePart1; - } - else if (i == queue.size() - 1 && (oldLocation == StmtLocation::slRecursiveCTE || oldLocation == StmtLocation::slRecursivePart2)) { - info->location_ = StmtLocation::slRecursivePart2; - } - else if(oldLocation == StmtLocation::slRecursiveCTE || oldLocation == StmtLocation::slRecursivePart1 || oldLocation == StmtLocation::slRecursivePart2) { - info->location_ = StmtLocation::slCTE; - } - - IR* curIR = queue[i]; - Table* tmp = nullptr; - - switch (curIR->type_) { - case IRTYPE::kQueryPrimary: { - tmp = instantiate_query_primary(NT_check(curIR, IRTYPE::kQueryPrimary)); - break; - } - case IRTYPE::kQueryExpressionParens: { - IR* query_expression_parens = NT_check(curIR, IRTYPE::kQueryExpressionParens); - while (query_expression_parens->left_->type_ == IRTYPE::kQueryExpressionParens) { - query_expression_parens = NT_check(query_expression_parens->left_, IRTYPE::kQueryExpressionParens); - } - - tmp = instantiate_query_expression(NT_check(query_expression_parens->left_, IRTYPE::kQueryExpression)); - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); - assert(0); - } - } - - if (i == 0) { - res = tmp; - - if (curIR->type_ == IRTYPE::kQueryPrimary) { - if (!info->has_column_limit()) { - info->columnNumber_ = res->columns_.size(); - } - - if (info->recursiveCteName_ != UNREFERENCE && info->recursiveCte_ == nullptr) { - res->identifierName_ = info->recursiveCteName_; - info->recursiveCte_ = res; - } - } - } - else { - delete tmp; - } - } - - info->location_ = oldLocation; - - return res; -} - -void Instantiator::instantiate_with_clause(IR* with_clause) { - StmtLocation location = StmtLocation::slCTE; - - IR* with_list = NT_check(with_clause->left_, IRTYPE::kWithList); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - info->clear_cte(); - - if (with_clause->op_->prefix_ == TERMINAL::tWithRecursive) { - location = StmtLocation::slRecursiveCTE; - } - - while (with_list != nullptr) { - IR* common_table_expr = NT_check(with_list->left_, IRTYPE::kCommonTableExpr); - - IR* table_name = NT_check(common_table_expr->left_, IRTYPE::kTableName); - IR* opt_column_list = NT_check(common_table_expr->right_->left_, IRTYPE::kOptColumnList); - IR* subquery = NT_check(common_table_expr->right_->right_, IRTYPE::kSubquery); - - name_t tableName = globalStatusManger_->get_new_table_name(); - if (location == StmtLocation::slRecursiveCTE) { - info->recursiveCteName_ = tableName; - } - - info->update_acceColumns(); - - IR* curNode = subquery->left_; - while (curNode->type_ != IRTYPE::kQueryExpression) { - curNode = curNode->left_; - } - - Table* table = instantiate_query_expression(curNode, location, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - table->isSubQuery_ = true; - table->identifierName_ = tableName; - - instantiate_ident(table_name, IdentifierType::iTable, tableName); - - if (opt_column_list->left_) { - IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); - instantiate_column_list(column_list, table->columns_); - } - - info->innerCteTables_.push_back(table); - - info->recursiveCteName_ = UNREFERENCE; - info->acceColumns_.clear(); - - with_list = with_list->right_; - } - - return; -} -void Instantiator::instantiate_order_clause(IR* order_clause) { - IR* order_list = NT_check(order_clause->left_, IRTYPE::kOrderList); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - while (order_list != nullptr) { - IR* expr_root = NT_check(order_list->left_->left_, IRTYPE::kExprRoot); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slOrderClause); - info->add_out_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - order_list = order_list->right_; - } - - return; -} -void Instantiator::instantiate_limit_clause(IR* limit_clause) { - IR* limit_options = NT_check(limit_clause->left_, IRTYPE::kLimitOptions); - IR* iconst_1 = NT_check(limit_options->left_, IRTYPE::kIconst); - IR* iconst_2 = (limit_options->right_ == nullptr) ? nullptr : NT_check(limit_options->right_, IRTYPE::kIconst); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (info->has_row_limit()) { - iconst_1->long_val_ = exprInstantiator_->get_random_integer(info->rowNumber_, info->rowNumber_); - info->rowNumber_ = DEFAULTROWNUMBER; - } - else { - iconst_1->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); - } - - if (iconst_2 != nullptr) { - iconst_2->long_val_ = exprInstantiator_->get_random_integer(OFFSETMIN, OFFSETMAX); - } - - return; -} - -Table* Instantiator::instantiate_select_item_list(IR* select_item_list) { - IR* t_select_item_list = select_item_list; - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - Table* res = new Table(UNREFERENCE, IdentifierType::iTable, info); - - int columnCount = 0; - while (t_select_item_list != nullptr) { - IR* select_item = NT_check(t_select_item_list->left_, IRTYPE::kSelectItem); - - if (info->location_ == StmtLocation::slRecursivePart1 && columnCount == 0) { - deep_delete(select_item->left_); - deep_delete(select_item->right_); - - select_item->left_ = deep_copy(IRTrim_->simple_expr_root_); - select_item->right_ = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), deep_copy(IRTrim_->simple_alias_), nullptr); - - IR* alias = NT_check(select_item->right_->left_, IRTYPE::kAlias); - instantiate_ident(alias, IdentifierType::iColumn, RESERVEDCOLUMNNAME); - - bool tmp = res->add_column(new Column(RESERVEDCOLUMNNAME, ColumnType::ctInt)); - assert(tmp); - - columnCount++; - } - else { - if (select_item->left_->type_ == IRTYPE::kTableWild) { - bool success = false; - - if (!info->usedTables_.empty()) { - IR* table_wild = NT_check(select_item->left_, IRTYPE::kTableWild); - IR* table_name = nullptr; - - if (table_wild->left_ != nullptr) { - table_name = NT_check(table_wild->left_, IRTYPE::kTableName); - } - - if (table_name != nullptr) { - int index = exprInstantiator_->get_random_integer(0, info->usedTables_.size() - 1); - Table* table = info->usedTables_[index]; - - if (!info->exist_duplicated_column(res->columns_, table->columns_) && (!info->has_column_limit() || (columnCount + table->columns_.size()) <= info->columnNumber_)) { - instantiate_ident(table_name, IdentifierType::iTable, table->identifierName_); - - for (Column* c : table->columns_) { - bool tmp = res->add_column(new Column(c)); - assert(tmp); - } - - columnCount += table->columns_.size(); - success = true; - } - } - else { - vector columns; - - for (Table* t : info->usedTables_) { - for (Column* c : t->columns_) { - columns.push_back(c); - } - } - - if (!info->exist_duplicated_column(res->columns_, columns) && (!info->has_column_limit() || (columnCount + columns.size()) <= info->columnNumber_)) { - for (Column* c : columns) { - bool tmp = res->add_column(new Column(c)); - assert(tmp); - } - - columnCount += columns.size(); - success = true; - } - } - } - - if (!success) { - deep_delete(select_item->left_); - - select_item->left_ = deep_copy(IRTrim_->simple_expr_root_); - select_item->right_ = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), deep_copy(IRTrim_->simple_alias_), nullptr); - } - } - - if (select_item->left_->type_ == IRTYPE::kExprRoot) { - IR* expr_root = NT_check(select_item->left_, IRTYPE::kExprRoot); - IR* opt_alias = NT_check(select_item->right_, IRTYPE::kOptAlias); - - if (opt_alias->left_ == nullptr) { - opt_alias->left_ = deep_copy(IRTrim_->simple_alias_); - opt_alias->op_->prefix_ = TERMINAL::tAs; - } - - IR* alias = NT_check(opt_alias->left_, IRTYPE::kAlias); - - name_t newColumnName = res->get_acce_column_name(); - instantiate_ident(alias, IdentifierType::iColumn, newColumnName); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slTargetList); - info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - bool tmp = res->add_column(new Column(newColumnName, ColumnType::ctNull)); - assert(tmp); - - columnCount++; - } - } - - if (info->has_column_limit()) { - assert(info->columnNumber_ > 0); - - if (columnCount >= info->columnNumber_ && t_select_item_list->right_ != nullptr) { - deep_delete(t_select_item_list->right_); - - t_select_item_list->right_ = nullptr; - t_select_item_list->op_->middle_ = TERMINAL::tEmpty; - } - else if (columnCount < info->columnNumber_ && t_select_item_list->right_ == nullptr) { - t_select_item_list->right_ = deep_copy(IRTrim_->simple_select_item_list_); - t_select_item_list->op_->middle_ = TERMINAL::tOpComma; - } - } - - t_select_item_list = t_select_item_list->right_; - } - - assert(res->columns_.size() == columnCount); - - return res; -} -void Instantiator::instantiate_from_clause(IR* from_clause) { - IR* table_reference_list = NT_check(from_clause->left_, IRTYPE::kTableReferenceList); - - while (table_reference_list != nullptr) { - IR* table_reference = NT_check(table_reference_list->left_, IRTYPE::kTableReference); - instantiate_table_reference(table_reference); - - table_reference_list = table_reference_list->right_; - } - - return; -} -vector Instantiator::instantiate_table_reference(IR* table_reference) { - vector res; - vector queue; - - if (table_reference->left_->type_ == IRTYPE::kJoinedTable) { - IR* joined_table = NT_check(table_reference->left_, IRTYPE::kJoinedTable); - queue.push_back(joined_table); - } - else { - IR* table_factor = NT_check(table_reference->left_, IRTYPE::kTableFactor); - - switch (table_factor->left_->type_) { - case IRTYPE::kSingleTable: { - IR* single_table = NT_check(table_factor->left_, IRTYPE::kSingleTable); - queue.push_back(single_table); - - break; - } - case IRTYPE::kDerivedTable: { - IR* derived_table = NT_check(table_factor->left_, IRTYPE::kDerivedTable); - queue.push_back(derived_table); - - break; - } - case IRTYPE::kJoinedTableParens: { - IR* joined_table = NT_check(table_factor->left_->left_, IRTYPE::kJoinedTable); - queue.push_back(joined_table); - - break; - } - case IRTYPE::kTableReferenceListParens: { - IR* table_reference_list_parens = NT_check(table_factor->left_, IRTYPE::kTableReferenceListParens); - - while (table_reference_list_parens != nullptr) { - IR* t_table_reference = NT_check(table_reference_list_parens->left_, IRTYPE::kTableReference); - queue.push_back(t_table_reference); - - table_reference_list_parens = table_reference_list_parens->right_; - } - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown table_factor->left_->type_: %d\n", static_cast(table_factor->left_->type_)); - assert(0); - } - } - } - - assert(!queue.empty()); - for (int i = 0; i < queue.size(); i++) { - IR* curIR = queue[i]; - - switch (curIR->type_) { - case IRTYPE::kSingleTable: { - Table* table = instantiate_single_table(curIR); - res.push_back(table); - - break; - } - case IRTYPE::kDerivedTable: { - Table* table = instantiate_derived_table(curIR); - res.push_back(table); - - break; - } - case IRTYPE::kJoinedTable: { - vector tables = instantiate_joined_table(curIR); - - for (Table* table : tables) { - res.push_back(table); - } - - break; - } - case IRTYPE::kTableReference: { - vector tables = instantiate_table_reference(curIR); - - for (Table* table : tables) { - res.push_back(table); - } - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); - assert(0); - } - } - } - - return res; -} -Table* Instantiator::instantiate_single_table(IR* single_table) { - Table* res = nullptr; - Table* chosenTable = nullptr; - - IR* table_name = NT_check(single_table->left_, IRTYPE::kTableName); - IR* opt_alias = NT_check(single_table->right_, IRTYPE::kOptAlias); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (info->location_ == StmtLocation::slRecursivePart2 && info->recursiveCteName_ != UNREFERENCE && info->recursiveCte_ != nullptr) { - chosenTable = info->recursiveCte_; - - info->recursiveCteName_ = UNREFERENCE; - info->recursiveCte_ = nullptr; - } - else { - int index = globalStatusManger_->get_acce_table_number(); - assert(index > 0); - - int randomNumber = exprInstantiator_->get_random_integer(0, index - 1); - chosenTable = globalStatusManger_->get_acce_table(randomNumber); - } - - res = new Table(chosenTable, info); - instantiate_ident(table_name, res->identifierType_, res->identifierName_); - - if (info->is_duplicated_table(res) && opt_alias->left_ == nullptr) { - opt_alias->left_ = deep_copy(IRTrim_->simple_alias_); - opt_alias->op_->prefix_ = TERMINAL::tAs; - } - - if (opt_alias->left_ != nullptr) { - name_t newName = globalStatusManger_->get_new_table_name(); - IR* alias = NT_check(opt_alias->left_, IRTYPE::kAlias); - - instantiate_ident(alias, IdentifierType::iTable, newName); - - res->identifierName_ = newName; - } - - info->add_used_table(res); - - return res; -} -Table* Instantiator::instantiate_derived_table(IR* derived_table) { - Table* res = nullptr; - - IR* subquery = NT_check(derived_table->left_, IRTYPE::kSubquery); - IR* alias = NT_check(derived_table->right_->left_, IRTYPE::kAlias); - IR* opt_column_list = NT_check(derived_table->right_->right_, IRTYPE::kOptColumnList); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - if (derived_table->op_->prefix_ == TERMINAL::tLateral) { - info->update_acceColumns(); - } - else { - info->acceColumns_ = info->outReferences_; - } - - IR* curNode = subquery->left_; - while (curNode->type_ != IRTYPE::kQueryExpression) { - curNode = curNode->left_; - } - - res = instantiate_query_expression(curNode, StmtLocation::slTableReference, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - res->isSubQuery_ = true; - - name_t newName = globalStatusManger_->get_new_table_name(); - instantiate_ident(alias, IdentifierType::iTable, newName); - res->identifierName_ = newName; - - if (opt_column_list->left_ != nullptr) { - IR* column_list = NT_check(opt_column_list->left_, IRTYPE::kColumnList); - - for (Column* c: res->columns_) { - name_t name = res->get_acce_column_name(); - res->remove_column_name(name); - - if (name != UNREFERENCE) { - res->add_column_name(c->identifierName_); - c->identifierName_ = name; - } - } - - instantiate_column_list(column_list, res->columns_); - } - - info->acceColumns_.clear(); - info->add_used_table(res); - - return res; -} -vector Instantiator::instantiate_joined_table(IR* joined_table) { - bool isRightJoin = false; - vector res; - - IR* table_reference_left = nullptr; - IR* table_reference_right = nullptr; - IR* table_factor = nullptr; - IR* expr_root = nullptr; - IR* column_list = nullptr; - IR* joined_table_tmp = nullptr; - - IR* unknown = nullptr; - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - table_reference_left = NT_check(joined_table->left_, IRTYPE::kTableReference); - unknown = joined_table->right_; - - if (unknown->left_->type_ == IRTYPE::kNaturalJoinType) { - IR* natural_join_type = NT_check(unknown->left_, IRTYPE::kNaturalJoinType); - - if (natural_join_type->op_->prefix_ == TERMINAL::tNaturalRight) { - isRightJoin = true; - } - } - else if (unknown->left_->type_ == IRTYPE::kOuterJoinType) { - IR* outer_join_type = NT_check(unknown->left_, IRTYPE::kOuterJoinType); - - if (outer_join_type->op_->prefix_ == TERMINAL::tRight) { - isRightJoin = true; - } - } - - if (unknown->right_->type_ == IRTYPE::kTableReference) { - table_reference_right = NT_check(unknown->right_, IRTYPE::kTableReference); - } - else if (unknown->right_->type_ == IRTYPE::kTableFactor) { - table_factor = NT_check(unknown->right_, IRTYPE::kTableFactor); - } - else { - joined_table_tmp = unknown->right_; - - table_reference_right = NT_check(joined_table_tmp->left_, IRTYPE::kTableReference); - - if (joined_table_tmp->right_->type_ == IRTYPE::kExprRoot) { - expr_root = NT_check(joined_table_tmp->right_, IRTYPE::kExprRoot); - } - else { - column_list = NT_check(joined_table_tmp->right_, IRTYPE::kColumnList); - } - } - - if (table_factor != nullptr) { - table_reference_right = new IR(IRTYPE::kTableReference, OP0(), table_factor, nullptr); - } - - vector left; - vector right; - if (isRightJoin) { - right = instantiate_table_reference(table_reference_right); - left = instantiate_table_reference(table_reference_left); - } - else { - left = instantiate_table_reference(table_reference_left); - right = instantiate_table_reference(table_reference_right); - } - - if (table_factor != nullptr && table_reference_right->left_ == table_factor) { - table_reference_right->left_ = nullptr; - deep_delete(table_reference_right); - table_reference_right = nullptr; - } - - vector columnNames = vector(COLUMNNAMEMAX, 0); - for (Table* t : left) { - for (Column* c : t->columns_) { - columnNames[c->identifierName_]++; - } - - res.push_back(t); - } - - for (Table* t : right) { - for (Column* c : t->columns_) { - columnNames[c->identifierName_]++; - } - - res.push_back(t); - } - - if (column_list != nullptr) { - vector duplicatedColumnNames; - for (int i = 0; i < COLUMNNAMEMAX; i++) { - if (columnNames[i] > 1) { - duplicatedColumnNames.push_back(static_cast(i)); - } - } - - if (!duplicatedColumnNames.empty()) { - vector usedColumns; - - random_device rd; - mt19937 r_eng(rd()); - uniform_int_distribution dis(1, duplicatedColumnNames.size()); - - int max = dis(r_eng); - for (int i = 0; i < max; i++) { - usedColumns.push_back(duplicatedColumnNames[i]); - } - - instantiate_column_list(column_list, usedColumns); - } - else { - deep_delete(joined_table_tmp->right_); - joined_table_tmp->right_ = deep_copy(IRTrim_->simple_expr_root_true_); - - joined_table_tmp->op_->middle_ = TERMINAL::tOn; - joined_table_tmp->op_->suffix_ = TERMINAL::tEmpty; - - column_list = nullptr; - } - } - else if (expr_root != nullptr) { - info->update_acceColumns(res, columnNames); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slTableReference); - info->add_out_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - info->acceColumns_.clear(); - } - - return res; -} -void Instantiator::instantiate_where_clause(IR* where_clause) { - IR* expr_root = NT_check(where_clause->left_, IRTYPE::kExprRoot); - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slWhereClause); - info->add_out_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - if (info->location_ == StmtLocation::slRecursivePart2) { - IRTrim_->set_recursive_limit(expr_root); - } - - return; -} -void Instantiator::instantiate_group_clause(IR* group_clause) { - IR* expr_root_list = NT_check(group_clause->left_, IRTYPE::kExprRootList); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - int i = 0; - while (expr_root_list != nullptr && i < info->usedInnerColumns_.size()) { - IR* expr_root = IRTrim_->get_expr_root_columnref(info->usedInnerColumns_[i]); - - deep_delete(expr_root_list->left_); - expr_root_list->left_ = expr_root; - - i++; - - if (i < info->usedInnerColumns_.size() && expr_root_list->right_ == nullptr) { - expr_root_list->right_ = deep_copy(IRTrim_->simple_expr_root_list_); - expr_root_list->op_->middle_ = TERMINAL::tOpComma; - } - - expr_root_list = expr_root_list->right_; - } - - vector usedColumns; - while (expr_root_list != nullptr && !info->acceColumns_.empty()) { - int index = exprInstantiator_->get_random_integer(0, info->acceColumns_.size() - 1); - Column* randomColumn = info->acceColumns_[index]; - - IR* expr_root = IRTrim_->get_expr_root_columnref(randomColumn); - - deep_delete(expr_root_list->left_); - expr_root_list->left_ = expr_root; - - if (find(usedColumns.begin(), usedColumns.end(), randomColumn) == usedColumns.end()) { - usedColumns.push_back(randomColumn); - } - - expr_root_list = expr_root_list->right_; - } - - if (expr_root_list != nullptr) { - deep_delete(expr_root_list->left_); - expr_root_list->left_ = deep_copy(IRTrim_->simple_expr_root_); - - deep_delete(expr_root_list->right_); - - expr_root_list->right_ = nullptr; - expr_root_list->op_->middle_ = TERMINAL::tEmpty; - } - - info->add_out_usedColumns(usedColumns); - - return; -} -void Instantiator::instantiate_having_clause(IR* having_clause) { - IR* expr_root = NT_check(having_clause->left_, IRTYPE::kExprRoot); - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slHavingClause); - info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - return; -} -void Instantiator::instantiate_window_clause(IR* window_clause) { - IR* window_definition_list = NT_check(window_clause->left_, IRTYPE::kWindowDefinitionList); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - while (window_definition_list != nullptr) { - IR* window_definition = NT_check(window_definition_list->left_, IRTYPE::kWindowDefinition); - instantiate_window_definition(window_definition); - - window_definition_list = window_definition_list->right_; - } - - return; -} -void Instantiator::instantiate_window_definition(IR* window_definition) { - IR* window_name = NT_check(window_definition->left_, IRTYPE::kWindowName); - IR* window_spec = NT_check(window_definition->right_, IRTYPE::kWindowSpec); - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - name_t newWindowName = globalStatusManger_->get_new_window_name(); - instantiate_ident(window_name, IdentifierType::iWindow, newWindowName); - - WindowStatus windowStatus = instantiate_window_spec(window_spec); - - info->windowStatusRecord_[newWindowName] = windowStatus; - - return; -} -WindowStatus Instantiator::instantiate_window_spec(IR* window_spec) { - WindowStatus windowStatus = WindowStatus::wsNoInherit; - - IR* window_spec_details = nullptr; - - IR* opt_existing_window_name = nullptr; - IR* opt_partition_clause = nullptr; - IR* opt_window_order_by_clause = nullptr; - IR* opt_window_frame_clause = nullptr; - - IR* unknown = nullptr; - - SelectStmtInfo* info = globalStatusManger_->get_cur_selectInfo(); - - window_spec_details = NT_check(window_spec->left_, IRTYPE::kWindowSpecDetails); - - opt_existing_window_name = NT_check(window_spec_details->left_, IRTYPE::kOptExistingWindowName); - unknown = window_spec_details->right_; - - opt_partition_clause = NT_check(unknown->left_, IRTYPE::kOptPartitionClause); - unknown = unknown->right_; - - opt_window_order_by_clause = NT_check(unknown->left_, IRTYPE::kOptWindowOrderByClause); - opt_window_frame_clause = NT_check(unknown->right_, IRTYPE::kOptWindowFrameClause); - - if (opt_existing_window_name->left_ != nullptr) { - vector inheritedWindows; - - for (auto &it : info->windowStatusRecord_) { - if (it.second != WindowStatus::wsCantBeInherited) { - inheritedWindows.push_back(it.first); - } - } - - if (inheritedWindows.empty()) { - deep_delete(opt_existing_window_name->left_); - opt_existing_window_name->left_ = nullptr; - } - else { - int index = exprInstantiator_->get_random_integer(0, inheritedWindows.size() - 1); - name_t inheritedWindowName = inheritedWindows[index]; - - IR* t_window_name = NT_check(opt_existing_window_name->left_, IRTYPE::kWindowName); - instantiate_ident(t_window_name, IdentifierType::iWindow, inheritedWindowName); - - windowStatus = info->windowStatusRecord_[inheritedWindowName] == WindowStatus::wsWithOrder ? WindowStatus::wsWithOrder : WindowStatus::wsInherit; - } - } - - if (opt_partition_clause->left_ != nullptr) { - if (windowStatus == WindowStatus::wsNoInherit) { - IR* expr_root_list = NT_check(opt_partition_clause->left_, IRTYPE::kExprRootList); - - while (expr_root_list != nullptr) { - IR* expr_root = NT_check(expr_root_list->left_, IRTYPE::kExprRoot); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slWindowClause); - info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - expr_root_list = expr_root_list->right_; - } - } - else { - deep_delete(opt_partition_clause->left_); - - opt_partition_clause->left_ = nullptr; - opt_partition_clause->op_->prefix_ = TERMINAL::tEmpty; - } - } - - if (opt_window_order_by_clause->left_ != nullptr) { - if (windowStatus != WindowStatus::wsWithOrder) { - IR* order_list = NT_check(opt_window_order_by_clause->left_, IRTYPE::kOrderList); - - while (order_list != nullptr) { - IR* expr_root = NT_check(order_list->left_->left_, IRTYPE::kExprRoot); - - exprInstantiator_->instantiate_expr_root(expr_root, info->acceColumns_, StmtLocation::slWindowClause); - info->add_all_usedColumns(exprInstantiator_->usedColumnsBuffer_); - - order_list = order_list->right_; - } - - windowStatus = WindowStatus::wsWithOrder; - } - else { - deep_delete(opt_window_order_by_clause->left_); - - opt_window_order_by_clause->left_ = nullptr; - opt_window_order_by_clause->op_->prefix_ = TERMINAL::tEmpty; - } - } - - if (opt_window_frame_clause->left_ != nullptr) { - IR* window_frame_units = NT_check(opt_window_frame_clause->left_, IRTYPE::kWindowFrameUnits); - IR* window_frame_extent = NT_check(opt_window_frame_clause->right_, IRTYPE::kWindowFrameExtent); - - if (windowStatus != WindowStatus::wsWithOrder) { - window_frame_units->op_->prefix_ = TERMINAL::tRows; - } - - stack IRStack; - vector iconsts; - IRStack.push(window_frame_extent); - - while (!IRStack.empty()) { - IR* curIR = IRStack.top(); - IRStack.pop(); - - if (curIR == nullptr) { - continue; - } - else if (curIR->type_ == IRTYPE::kIconst) { - iconsts.push_back(curIR); - } - else { - IRStack.push(curIR->right_); - IRStack.push(curIR->left_); - } - } - - for (IR* curIR : iconsts) { - curIR->long_val_ = exprInstantiator_->get_random_integer(LIMITMIN, LIMITMAX); - } - - windowStatus = WindowStatus::wsCantBeInherited; - } - - return windowStatus; -} - -void Instantiator::instantiate_column_list(IR* column_list, vector& columns) { - int i = 0; - - while (column_list != nullptr && i < columns.size()) { - IR* column_name = NT_check(column_list->left_, IRTYPE::kColumnName); - instantiate_ident(column_name, IdentifierType::iColumn, columns[i]); - - i++; - - if (i == columns.size() && column_list->right_ != nullptr) { - deep_delete(column_list->right_); - - column_list->right_ = nullptr; - column_list->op_->middle_ = TERMINAL::tEmpty; - } - else if (i != columns.size() && column_list->right_ == nullptr) { - column_list->right_ = deep_copy(IRTrim_->simple_column_list_); - column_list->op_->middle_ = TERMINAL::tOpComma; - } - - column_list = column_list->right_; - } - - return; -} -void Instantiator::instantiate_column_list(IR* column_list, vector& columns) { - vector columnNames; - - for (Column* c : columns) { - columnNames.push_back(c->identifierName_); - } - - instantiate_column_list(column_list, columnNames); - - return; -} -void Instantiator::instantiate_key_list(IR* key_list, vector& columns) { - int count = 0; - IR* curNode = key_list; - while (curNode != nullptr && count < columns.size()) { - IR* key_part = NT_check(curNode->left_, IRTYPE::kKeyPart); - IR* column_name = NT_check(key_part->left_, IRTYPE::kColumnName); - IR* iconst = nullptr; - - instantiate_ident(column_name, IdentifierType::iColumn, columns[count]->identifierName_); - - if (key_part->right_->type_ != IRTYPE::kOptOrderingDirection) { - if (Column::typeToBasicType_[columns[count]->columnType_] != ColumnBasicType::ctString) { - deep_delete(key_part->right_); - key_part->right_ = new IR(IRTYPE::kOptOrderingDirection, OP0(), nullptr, nullptr); - } - else { - iconst = NT_check(key_part->right_->left_, IRTYPE::kIconst); - } - } - - if (iconst != nullptr) { - int v1 = exprInstantiator_->get_random_integer(1, 32); - iconst->long_val_ = v1; - } - - count++; - - if (count == columns.size() && curNode->right_ != nullptr) { - deep_delete(curNode->right_); - - curNode->right_ = nullptr; - curNode->op_->middle_ = TERMINAL::tEmpty; - } - else if (count != columns.size() && curNode->right_ == nullptr) { - curNode->right_ = deep_copy(IRTrim_->simple_key_part_list_); - curNode->op_->middle_ = TERMINAL::tOpComma; - } - - curNode = curNode->right_; - } - - return; -} -void Instantiator::instantiate_ident(IR* identifier_name, IdentifierType type, name_t name) { - IR* ident = NT_check(identifier_name->left_, IRTYPE::kIdent); - - switch(type) { - case IdentifierType::iColumn: { - ident->str_val_ = "c" + to_string(name); - break; - } - case IdentifierType::iTable: { - ident->str_val_ = "t" + to_string(name); - break; - } - case IdentifierType::iWindow: { - ident->str_val_ = "w" + to_string(name); - break; - } - case IdentifierType::iIndex: { - ident->str_val_ = "i" + to_string(name); - break; - } - case IdentifierType::iConstraint: { - ident->str_val_ = "cc" + to_string(name); - break; - } - case IdentifierType::iView: { - ident->str_val_ = "v" + to_string(name); - break; - } - default: { - fprintf(stderr, "ERROR: Unknown Ident Type: %d\n", static_cast(type)); - assert(0); - } - } - - return; -} - -bool Instantiator::check_foreign_key(Table* table, vector& curTableColumn, vector& otherTableColumn) { - vector types; - - vector acceTable = globalStatusManger_->get_acce_table(IdentifierType::iTable); - acceTable.push_back(table); - - for (Column* c : table->columns_) { - types.push_back(c->columnType_); - } - - Table* chosenTable = acceTable[rand() % acceTable.size()]; - for (Index* index : chosenTable->indexes_) { - bool flag = false; - - for (auto& it : index->columns_) { - if (find(types.begin(), types.end(), it.first->columnType_) == types.end() || it.second == IndexType::itFunctional) { - continue; - } - - for (Column* column : table->columns_) { - if (column->columnType_ != it.first->columnType_ || it.first == column) { - continue; - } - - if (find(curTableColumn.begin(), curTableColumn.end(), column) == curTableColumn.end()) { - curTableColumn.push_back(column); - otherTableColumn.push_back(it.first); - - flag = true; - break; - } - } - } - - if (flag == true) { - break; - } - } - - if (curTableColumn.empty() || curTableColumn.size() != otherTableColumn.size()) { - return false; - } - - return true; -} - -//-----------------------------ExprInstantiator----------------------------- -void ExprInstantiator::instantiate_expr_root(IR* expr_root, vector& acceColumns, StmtLocation location) { - usedColumnsBuffer_.clear(); - - IR* expr = NT_check(expr_root->left_, IRTYPE::kExpr); - instantiate_expr(expr, acceColumns, location); - - return; -} -void ExprInstantiator::instantiate_expr(IR* expr, vector& acceColumns, StmtLocation location) { - stack IRStack; - vector queue; - - IRStack.push(expr); - - while (!IRStack.empty()) { - IR* curIR = IRStack.top(); - IRStack.pop(); - - if (curIR == nullptr) { - continue; - } - - switch (curIR->type_) { - case IRTYPE::kAllSubquery: - case IRTYPE::kInSubquery: { - queue.push_back(curIR); - break; - } - case IRTYPE::kSimpleExpr: { - if (find(ignoreSimpleExpr_.begin(), ignoreSimpleExpr_.end(), curIR->left_->type_) != ignoreSimpleExpr_.end()) { - IRStack.push(curIR->left_); - } - else { - queue.push_back(curIR); - } - - break; - } - default: { - IRStack.push(curIR->left_); - IRStack.push(curIR->right_); - - break; - } - } - } - - for (IR* curIR : queue) { - assert(curIR->type_ == IRTYPE::kInSubquery || curIR->type_ == IRTYPE::kAllSubquery || curIR->type_ == IRTYPE::kSimpleExpr); - - if (curIR->type_ == IRTYPE::kSimpleExpr) { - instantiate_simple_expr(curIR, acceColumns, location); - } - else { - while (curIR->type_ != IRTYPE::kQueryExpression) { - curIR = curIR->left_; - } - - vector tmpUsedColumns = usedColumnsBuffer_; - Table* tmp = instantiator_->instantiate_query_expression(curIR, location, DEFAULTROWNUMBER, 1); - - delete tmp; - usedColumnsBuffer_ = tmpUsedColumns; - } - } - - return; -} -void ExprInstantiator::instantiate_simple_expr(IR* simple_expr, vector& acceColumns, StmtLocation location) { - assert(find(ignoreSimpleExpr_.begin(), ignoreSimpleExpr_.end(), simple_expr->left_->type_) == ignoreSimpleExpr_.end()); - - switch (simple_expr->left_->type_) { - case IRTYPE::kColumnref: { - if (!acceColumns.empty()) { - IR* columnref = NT_check(simple_expr->left_, IRTYPE::kColumnref); - - IR* table_name = nullptr; - IR* column_name = nullptr; - - if (columnref->right_ == nullptr) { - column_name = NT_check(columnref->left_, IRTYPE::kColumnName); - } - else { - table_name = NT_check(columnref->left_, IRTYPE::kTableName); - column_name = NT_check(columnref->right_, IRTYPE::kColumnName); - } - - int index = get_random_integer(0, acceColumns.size() - 1); - Column* column = acceColumns[index]; - - if (column->duplicated_ == ColumnStatus::csDuplication && table_name == nullptr) { - IR* tmp1 = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* tmp2 = new IR(IRTYPE::kTableName, OP0(), tmp1, nullptr); - - table_name = tmp2; - - columnref->left_ = table_name; - columnref->right_ = column_name; - columnref->op_->middle_ = TERMINAL::tOpDot; - } - - if (table_name != nullptr) { - name_t tableName = column->parentTable_->identifierName_; - instantiator_->instantiate_ident(table_name, IdentifierType::iTable, tableName); - } - - name_t columnName = column->identifierName_; - instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, columnName); - - if (find(usedColumnsBuffer_.begin(), usedColumnsBuffer_.end(), column) == usedColumnsBuffer_.end()) { - usedColumnsBuffer_.push_back(column); - } - } - else { - deep_delete(simple_expr->left_); - - simple_expr->left_ = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); - simple_expr->left_->long_val_ = get_random_integer(); - } - - break; - } - case IRTYPE::kIconst: { - IR* iconst = NT_check(simple_expr->left_, IRTYPE::kIconst); - iconst->long_val_ = (rand() % 10) == 0 ? get_random_integer() : get_random_integer(-128, 128); - - break; - } - case IRTYPE::kFconst: { - IR* fconst = NT_check(simple_expr->left_, IRTYPE::kFconst); - fconst->float_val_ = (rand() % 10) == 0 ? get_random_float() : get_random_float(-128, 128); - - break; - } - case IRTYPE::kSconst: { - IR* sconst = NT_check(simple_expr->left_, IRTYPE::kSconst); - sconst->str_val_ = get_random_string(MINSTRINGLENGTH, MAXSTRINGLENGTH); - - break; - } - case IRTYPE::kSubquery: { - IR* subquery = NT_check(simple_expr->left_, IRTYPE::kSubquery); - - IR* curNode = subquery->left_; - while (curNode->type_ != IRTYPE::kQueryExpression) { - curNode = curNode->left_; - } - - Table* tmp = nullptr; - vector tmpUsedColumns = usedColumnsBuffer_; - - if (simple_expr->op_->prefix_ == TERMINAL::tExists) { - tmp = instantiator_->instantiate_query_expression(curNode, StmtLocation::slTargetList, DEFAULTROWNUMBER, DEFAULTCOLUMNNUMBER); - } - else { - tmp = instantiator_->instantiate_query_expression(curNode, StmtLocation::slTargetList, 1, 1); - } - - delete tmp; - usedColumnsBuffer_ = tmpUsedColumns; - - break; - } - case IRTYPE::kTypeCast: { - IR* type_cast = NT_check(simple_expr->left_, IRTYPE::kTypeCast); - instantiate_type_cast(type_cast, acceColumns, location); - - break; - } - case IRTYPE::kFunction: { - IR* function = NT_check(simple_expr->left_, IRTYPE::kFunction); - instantiate_function(function, acceColumns, location); - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown simple_expr->left_->type_: %d\n", static_cast(simple_expr->left_->type_)); - assert(0); - } - } - - return; -} -void ExprInstantiator::instantiate_type_cast(IR* type_cast, vector& acceColumns, StmtLocation location) { - IR* expr = NT_check(type_cast->left_, IRTYPE::kExpr); - IR* cast_type = NT_check(type_cast->right_, IRTYPE::kCastType); - - if (cast_type->left_ != nullptr && cast_type->left_->left_ != nullptr) { - IR* tmp = cast_type->left_; - - if (tmp->left_->type_ == IRTYPE::kFieldLength) { - IR* field_length = NT_check(tmp->left_, IRTYPE::kFieldLength); - IR* iconst = NT_check(field_length->left_, IRTYPE::kIconst); - - iconst->long_val_ = get_random_integer(1, LONG_MAX); - } - else if (tmp->left_->type_ == IRTYPE::kPrecision) { - IR* precision = NT_check(tmp->left_, IRTYPE::kPrecision); - - IR* iconst_left = NT_check(precision->left_, IRTYPE::kIconst); - IR* iconst_right = NT_check(precision->right_, IRTYPE::kIconst); - - iconst_left->long_val_ = get_random_integer(1, 65); - iconst_right->long_val_ = get_random_integer(1, min(static_cast(iconst_left->long_val_), 30)); - } - else { - fprintf(stderr, "ERROR: Unknown cast_type->left_->left_->type_: %d\n", static_cast(cast_type->left_->left_->type_)); - assert(0); - } - } - - instantiate_expr(expr, acceColumns, location); - - return; -} -void ExprInstantiator::instantiate_function(IR* function, vector& acceColumns, StmtLocation location) { - switch (function->left_->type_) { - case IRTYPE::kControlFunction: - case IRTYPE::kMathFunction: - case IRTYPE::kStringFunction: { - stack IRStack; - vector queue; - - IRStack.push(function->left_); - while (!IRStack.empty()) { - IR* curIR = IRStack.top(); - IRStack.pop(); - - if (curIR == nullptr) { - continue; - } - - if (curIR->type_ == IRTYPE::kExpr) { - queue.push_back(curIR); - } - else { - IRStack.push(curIR->left_); - IRStack.push(curIR->right_); - } - } - - for (IR* expr : queue) { - assert(expr->type_ == IRTYPE::kExpr); - - instantiate_expr(expr, acceColumns, location); - } - - break; - } - case IRTYPE::kAggregateFunction: { - if (location != StmtLocation::slTargetList && location != StmtLocation::slHavingClause && location != StmtLocation::slWindowClause) { - deep_delete(function->left_); - function->left_ = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - - break; - } - - IR* aggregate_function = NT_check(function->left_, IRTYPE::kAggregateFunction); - instantiate_aggregate_function(aggregate_function, acceColumns, location); - - break; - } - case IRTYPE::kWindowFunction: { - if (location != StmtLocation::slTargetList) { - deep_delete(function->left_); - function->left_ = new IR(IRTYPE::kMathFunction, OP3(TERMINAL::tRandOpLpOpRp, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - - break; - } - - IR* window_function = NT_check(function->left_, IRTYPE::kWindowFunction); - instantiate_window_function(window_function, acceColumns, location); - - break; - } - default: { - fprintf(stderr, "ERROR: Unknown function->left_->type_: %d\n", static_cast(function->left_->type_)); - assert(0); - } - } - - return; -} -void ExprInstantiator::instantiate_aggregate_function(IR* aggregate_function, vector& acceColumns, StmtLocation location) { - stack IRStack; - vector queue; - vector captureType = { IRTYPE::kExpr, IRTYPE::kWindowingClause, IRTYPE::kOrderClause, IRTYPE::kSconst }; - - SelectStmtInfo* info = instantiator_->globalStatusManger_->get_cur_selectInfo(); - - IRStack.push(aggregate_function); - while (!IRStack.empty()) { - IR* curIR = IRStack.top(); - IRStack.pop(); - - if (curIR == nullptr) { - continue; - } - - if (find(captureType.begin(), captureType.end(), curIR->type_) != captureType.end()) { - queue.push_back(curIR); - } - else { - IRStack.push(curIR->left_); - IRStack.push(curIR->right_); - } - } - - for (IR* curIR : queue) { - switch (curIR->type_) { - case IRTYPE::kExpr: { - instantiate_expr(curIR, acceColumns, location); - break; - } - case IRTYPE::kWindowingClause: { - IR* window_name_or_spec = NT_check(curIR->left_, IRTYPE::kWindowNameOrSpec); - - if (info->windowStatusRecord_.empty() && window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { - deep_delete(window_name_or_spec->left_); - window_name_or_spec->left_ = deep_copy(instantiator_->IRTrim_->simple_window_spec_); - } - - if (window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { - IR* window_name = NT_check(window_name_or_spec->left_, IRTYPE::kWindowName); - - vector windowNames; - for (auto &it : info->windowStatusRecord_) { - windowNames.push_back(it.first); - } - - assert(!windowNames.empty()); - - int index = get_random_integer(0, windowNames.size() - 1); - name_t windowName = windowNames[index]; - - instantiator_->instantiate_ident(window_name, IdentifierType::iWindow, windowName); - } - else { - IR* window_spec = NT_check(window_name_or_spec->left_, IRTYPE::kWindowSpec); - instantiator_->instantiate_window_spec(window_spec); - } - - break; - } - case IRTYPE::kOrderClause: { - instantiator_->instantiate_order_clause(curIR); - break; - } - case IRTYPE::kSconst: { - curIR->str_val_ = get_random_string(MINSTRINGLENGTH, MAXSTRINGLENGTH); - break; - } - default: { - fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); - assert(0); - } - } - } - - info->hasAggregate = true; - - return; -} -void ExprInstantiator::instantiate_window_function(IR* window_function, vector& acceColumns, StmtLocation location) { - stack IRStack; - vector queue; - vector captureType = { IRTYPE::kExpr, IRTYPE::kWindowingClause, IRTYPE::kIconst }; - - SelectStmtInfo* info = instantiator_->globalStatusManger_->get_cur_selectInfo(); - - IRStack.push(window_function); - - while (!IRStack.empty()) { - IR* curIR = IRStack.top(); - IRStack.pop(); - - if (curIR == nullptr) { - continue; - } - - if (find(captureType.begin(), captureType.end(), curIR->type_) != captureType.end()) { - queue.push_back(curIR); - } - else { - IRStack.push(curIR->left_); - IRStack.push(curIR->right_); - } - } - - for (IR* curIR : queue) { - switch (curIR->type_) { - case IRTYPE::kExpr: { - instantiate_expr(curIR, acceColumns, location); - break; - } - case IRTYPE::kWindowingClause: { - IR* window_name_or_spec = NT_check(curIR->left_, IRTYPE::kWindowNameOrSpec); - - if (info->windowStatusRecord_.empty() && window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { - deep_delete(window_name_or_spec->left_); - window_name_or_spec->left_ = deep_copy(instantiator_->IRTrim_->simple_window_spec_); - } - - if (window_name_or_spec->left_->type_ == IRTYPE::kWindowName) { - IR* window_name = NT_check(window_name_or_spec->left_, IRTYPE::kWindowName); - - vector windowNames; - for (auto &it : info->windowStatusRecord_) { - windowNames.push_back(it.first); - } - - assert(!windowNames.empty()); - - int index = get_random_integer(0, windowNames.size() - 1); - name_t windowName = windowNames[index]; - - instantiator_->instantiate_ident(window_name, IdentifierType::iWindow, windowName); - } - else { - IR* window_spec = NT_check(window_name_or_spec->left_, IRTYPE::kWindowSpec); - instantiator_->instantiate_window_spec(window_spec); - } - - break; - } - case IRTYPE::kIconst: { - curIR->long_val_ = get_random_integer(1, LONG_MAX); - break; - } - default: { - fprintf(stderr, "ERROR: Unknown curIR->type_: %d\n", static_cast(curIR->type_)); - assert(0); - } - } - } - - return; -} - -long int ExprInstantiator::get_random_integer(long int min, long int max) { - assert(min <= max); - - random_device rd; - mt19937 r_eng(rd()); - uniform_int_distribution dis(min, max); - - return dis(r_eng); -} -double ExprInstantiator::get_random_float(int min, int max) { - random_device rd; - mt19937 r_eng(rd()); - uniform_real_distribution dis(min, max); - - return dis(r_eng); -} -string ExprInstantiator::get_random_string(int minLength, int maxLength) { - random_device rd; - mt19937 r_eng(rd()); - uniform_int_distribution charNumber(32, 126); - uniform_int_distribution stringLength(minLength, maxLength); - - int length = stringLength(r_eng); - string res = "\'"; - - for (int i = 0; i < length; i++) { - char tmp = charNumber(r_eng); - - if (tmp == '\'' || tmp == '\\') { - res += "\\"; - } - - res += tmp; - } - - res += "\'"; - - return res; -} diff --git a/src/mutate.cpp b/src/mutate.cpp deleted file mode 100755 index d0108f5..0000000 --- a/src/mutate.cpp +++ /dev/null @@ -1,1359 +0,0 @@ -#include "../include/mutate.h" -#include "../include/ast.h" -#include "../include/define.h" - -#include "../parser/bison_parser.h" -#include "../parser/flex_lexer.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace std; -namespace fs = std::filesystem; - -double get_random_double(int min, int max) { - random_device rd; - mt19937 r_eng(rd()); - uniform_real_distribution dis(min, max); - - return dis(r_eng); -} - -//-----------------------------Mutator----------------------------- - -vector Mutator::stmtIRType_ = { - IRTYPE::kCreateTableStmt, - IRTYPE::kCreateViewStmt, - IRTYPE::kCreateIndexStmt, - IRTYPE::kSelectStmt, - IRTYPE::kDropIndexStmt, - IRTYPE::kDropTableStmt, - IRTYPE::kDropViewStmt, - IRTYPE::kDeleteStmt, - IRTYPE::kUpdateStmt, - IRTYPE::kInsertStmt, - IRTYPE::kAlterTableStmt -}; -vector Mutator::clauseIRType_ = { - IRTYPE::kAlterListItem, - IRTYPE::kValues, - IRTYPE::kUpdateElem, - IRTYPE::kDefaultAttribute, - IRTYPE::kCheckConstraint, - IRTYPE::kKeyPartWithExpression, - IRTYPE::kOptWindowClause, - IRTYPE::kOptHavingClause, - IRTYPE::kWhereClause, - IRTYPE::kFromClause, - IRTYPE::kSelectItem -}; - -Mutator::Mutator() { - random_device rd; - srand(rd()); - - startTime = chrono::steady_clock::now(); - - not_mutatable_types_.insert({ IRTYPE::kParseToplevel, IRTYPE::kStmtmulti, IRTYPE::kStmt }); - - return; -} -Mutator::~Mutator() { - free_IR_library(); - free_IR_config_info(); - - return; -} - -bool Mutator::init_IR_library(string dirPath) { - vector IRFileNames = get_all_files_in_dir(dirPath.c_str()); - if (IRFileNames.empty()) { - fprintf(stderr, "ERROR: No IR library File in dirPath!!!\n"); - return false; - } - - for (string fileName : IRFileNames) { - ifstream inputFile(fileName); - string sql; - - while (getline(inputFile, sql)) { - if (sql.empty()) - continue; - - IR* p = IR_parser(sql.c_str()); - if (p == nullptr) - continue; - - add_ir_to_library(p); - deep_delete(p); - } - } - - return true; -} - -void Mutator::free_IR_library() { - for (IR* p : IR_library_[IRTYPE::kParseToplevel]) { - if (p) - deep_delete(p); - } - - return; -} - -bool Mutator::init_IR_config_info(string filePath) { - char flag = 0; - IRTYPE type = IRTYPE::kNone; - int count = 0; - - FILE* fd = fopen(filePath.c_str(), "r"); - if (!fd){ - fprintf(stderr, "IR_config file is not exists!!\n"); - return false; - } - - while (!feof(fd)) { - if (!flag) { - int tmpType = 0; - fscanf(fd, "%d %d\n", &tmpType, &count); - - type = static_cast(tmpType); - - if (IRInfo_.find(static_cast(type)) != IRInfo_.end()) { - fprintf(stderr, "ERROR: IR_config file has duplication type: %d!!\n", type); - return false; - } - - IRInfo_[type] = new IRInfoManger(); - IRInfo_[type]->curIRType_ = type; - - OpInfo_[type] = new OperatorManger(); - OpInfo_[type]->curIRType_ = type; - - IRTypeCount_[type] = { 0, 0 }; - - flag = 1; - } - else { - int prefix = 0; - int left = 0; - int middle = 0; - int right = 0; - int suffix = 0; - - for (int i = 0; i < count; i++) { - fscanf(fd, "%d %d %d %d %d\n", &prefix, &left, &middle, &right, &suffix); - - IRInfomation* tmp = new IRInfomation(prefix, left, middle, right, suffix); - IRInfo_[type]->add_IRInfomation(tmp); - } - - flag = 0; - type = IRTYPE::kNone; - count = 0; - } - } - - fclose(fd); - - return true; -} - -void Mutator::free_IR_config_info() { - for (auto& it : IRInfo_) { - delete it.second; - } - - for (auto& it : OpInfo_) { - delete it.second; - } - - return; -} - -uint64_t Mutator::hash(string& sql) { - const void* key = static_cast(sql.c_str()); - int len = sql.size(); - - const uint64_t m = 0xc6a4a7935bd1e995; - const int r = 47; - uint64_t h = 0xdeadbeefdeadbeef ^ (len * m); - - const uint64_t* data = static_cast(key); - const uint64_t* end = data + (len / 8); - - while (data != end) - { - uint64_t k = *data++; - - k *= m; - k ^= k >> r; - k *= m; - - h ^= k; - h *= m; - } - - const unsigned char* data2 = (const unsigned char*)data; - - switch (len & 7) - { - case 7: h ^= uint64_t(data2[6]) << 48; - case 6: h ^= uint64_t(data2[5]) << 40; - case 5: h ^= uint64_t(data2[4]) << 32; - case 4: h ^= uint64_t(data2[3]) << 24; - case 3: h ^= uint64_t(data2[2]) << 16; - case 2: h ^= uint64_t(data2[1]) << 8; - case 1: h ^= uint64_t(data2[0]); - h *= m; - }; - - h ^= h >> r; - h *= m; - h ^= h >> r; - - return h; -} - -vector Mutator::get_all_files_in_dir(const char* dirPath) { - vector res; - - fs::path dir = dirPath; - if (!fs::exists(dir)) { - return res; - } - - for (const fs::directory_entry& entry : fs::directory_iterator(dir)) { - if (entry.is_regular_file()) { - res.push_back(entry.path().string()); - } - } - - return res; -} - -ParseToplevel* Mutator::parser(const char* sql) { - - yyscan_t scanner; - YY_BUFFER_STATE state; - ParseToplevel* p = new ParseToplevel(); - - if (ff_lex_init(&scanner)) { - return NULL; - } - - state = ff__scan_string(sql, scanner); - - int ret = ff_parse(p, scanner); - - ff__delete_buffer(state, scanner); - ff_lex_destroy(scanner); - - if (ret != 0) { - p->deep_delete(); - return NULL; - } - - return p; -} - -IR* Mutator::IR_parser(const char* sql) { - ParseToplevel* p = parser(sql); - if (p == nullptr) - return nullptr; - - IR* res = p->translate(); - p->deep_delete(); - - return res; -} - -bool Mutator::add_ir_to_library(IR* root) { - extract_struct(root); - IR* newRoot = deep_copy(root); - - if (!add_ir_to_library_no_deepcopy(newRoot)) { - deep_delete(newRoot); - return false; - } - - return true; -} - -bool Mutator::add_ir_to_library_no_deepcopy(IR* root) { - bool flag = false; - - if (root->left_) flag |= add_ir_to_library_no_deepcopy(root->left_); - - if (root->right_) flag |= add_ir_to_library_no_deepcopy(root->right_); - - IRTYPE type = root->type_; - - string tmpStr = root->to_string(); - uint64_t h = hash(tmpStr); - if (find(IR_library_hash_[type].begin(), IR_library_hash_[type].end(), h) != IR_library_hash_[type].end()) { - if ((type == IRTYPE::kParseToplevel) && flag) { - IR_library_[type].push_back(root); - } - - return false | flag; - } - - IR_library_[type].push_back(root); - IR_library_hash_[type].insert(h); - - return true; -} - -void Mutator::extract_struct(IR* root) { - IRTYPE type = root->type_; - - if (root->left_) extract_struct(root->left_); - if (root->right_) extract_struct(root->right_); - - if (root->left_ || root->right_) return; - - switch (root->type_) { - case IRTYPE::kIconst: - root->long_val_ = 1; - break; - case IRTYPE::kFconst: - root->float_val_ = 1.0; - break; - case IRTYPE::kSconst: - root->str_val_ = "'x'"; - break; - case IRTYPE::kIdent: - root->str_val_ = "x"; - break; - } - - return; -} - -void Mutator::update_status(InputInfo* input, unsigned int execStatus, bool isValid) { - unsigned int reward = get_cur_reward(); - bool hasNewCoverage = (execStatus == 1 || execStatus == 2); - - IRInfoManger* manger = IRInfo_[input->MutateIRType_]; - manger->update_count(&input->MutateContext_, input->MutateIRInfoItem_, hasNewCoverage, reward); - -#ifdef ORIGINAL - OperatorManger* OpManger = OpInfo_[input->MutateIRType_]; - OpManger->update_count(&input->MutateContext_, input->MutateOperatorItem_, hasNewCoverage, reward); -#endif - - if (hasNewCoverage == true){ - if (execStatus == 1) { - IRTypeCount_[input->MutateIRType_].first += reward; - } - else{ - IRTypeCount_[input->MutateIRType_].first += reward * REWARDNEWCOVERAGE; - } - - if (isValid == true) { - add_ir_to_library(input->input_); - } - } - else { - IRTypeCount_[input->MutateIRType_].second += reward; - } - - return; -} - -vector Mutator::mutate_all(const char* sql) { - vector res; - deque> q; - - vector IRTypeRank; - vector probabilityRank; - - map>> indexes; - - IR* originRoot = IR_parser(sql); - if (originRoot == nullptr) - return res; - - IRContextS tmp = { 0 }; - q.push_back({originRoot, tmp}); - - while (!q.empty()) { - IR* curIR = q.front().first; - IRContextS curContext = q.front().second; - q.pop_front(); - - if (curIR == nullptr) { - continue; - } - - IRContextS nextContext = { 0 }; - - if (find(stmtIRType_.begin(), stmtIRType_.end(), curIR->type_) != stmtIRType_.end()) { - nextContext.stmt_ = static_cast(curIR->type_); - } - else { - nextContext.stmt_ = curContext.stmt_; - } - - if (find(clauseIRType_.begin(), clauseIRType_.end(), curIR->type_) != clauseIRType_.end()) { - nextContext.clause_ = static_cast(curIR->type_); - } - else { - nextContext.clause_ = curContext.clause_; - } - - if (curIR->type_ == IRTYPE::kSubquery) { - nextContext.inSubquery_ = 1; - } - else { - nextContext.inSubquery_ = curContext.inSubquery_; - } - - nextContext.parentIRType_ = curIR->type_; - nextContext.parentIRItem_ = IRInfo_[curIR->type_]->get_index_of_IRInfo(curIR); - - q.push_back({curIR->left_, nextContext }); - q.push_back({ curIR->right_ , nextContext }); - - if (not_mutatable_types_.find(curIR->type_) != not_mutatable_types_.end()) { - continue; - } - - unsigned int chosenNumber = IRTypeCount_[curIR->type_].first + IRTypeCount_[curIR->type_].second; - if (find(IRTypeRank.begin(), IRTypeRank.end(), curIR->type_) == IRTypeRank.end() && chosenNumber > IRTYPEUPDATETHRESHOLD) { - if (IRTypeRank.size() < TOPNUMBER) { - IRTypeRank.push_back(curIR->type_); - } - else { - IRTYPE tLeft = IRTypeRank[IRTypeRank.size() - 1]; - - double pLeft = static_cast(IRTypeCount_[tLeft].first) / (IRTypeCount_[tLeft].first + IRTypeCount_[tLeft].second); - double pRight = static_cast(IRTypeCount_[curIR->type_].first) / chosenNumber; - - if (pLeft < pRight) { - IRTypeRank[IRTypeRank.size() - 1] = curIR->type_; - } - } - } - - for (int i = IRTypeRank.size() - 1; i > 0; i--) { - IRTYPE tLeft = IRTypeRank[i - 1]; - IRTYPE tRight = IRTypeRank[i]; - - double pLeft = static_cast(IRTypeCount_[tLeft].first) / (IRTypeCount_[tLeft].first + IRTypeCount_[tLeft].second); - double pRight = static_cast(IRTypeCount_[tRight].first) / (IRTypeCount_[tRight].first + IRTypeCount_[tRight].second); - - if (pLeft > pRight) { - break; - } - - IRTYPE tmp = IRTypeRank[i]; - IRTypeRank[i] = IRTypeRank[i - 1]; - IRTypeRank[i - 1] = tmp; - } - - indexes[curIR->type_].push_back({ curIR, curContext }); - } - - double expectSum = 0; - for (IRTYPE t : IRTypeRank) { - expectSum += static_cast(IRTypeCount_[t].first) / (IRTypeCount_[t].first + IRTypeCount_[t].second); - } - - for (int i = 0; i < IRTypeRank.size(); i++) { - IRTYPE t = IRTypeRank[i]; - double p = static_cast(IRTypeCount_[t].first) / (IRTypeCount_[t].first + IRTypeCount_[t].second); - - probabilityRank.push_back(p / expectSum); - } - - double heat = get_cur_heat(); - for (auto& it : indexes) { - IRTYPE curType = it.first; - unsigned int chosenNumber = IRTypeCount_[curType].first + IRTypeCount_[curType].second; - - for (pair& node : it.second) { - IR* curNode = nullptr; - IRContextS curContext = { 0 }; - - double randomNumber = get_random_double(0, 1); - - if (chosenNumber < IRTYPEUPDATETHRESHOLD || randomNumber < heat) { - curNode = node.first; - curContext = node.second; - } - else { - double tmpRand = get_random_double(0, 1); - IRTYPE tmpType = IRTYPE::kNone; - - for (int i = 0; i < probabilityRank.size(); i++) { - if (tmpRand >= probabilityRank[i]) { - tmpRand -= probabilityRank[i]; - continue; - } - - tmpType = IRTypeRank[i]; - break; - } - - if (tmpType == IRTYPE::kNone) { - curNode = node.first; - curContext = node.second; - } - else { - pair& tmp = indexes[tmpType][rand() % indexes[tmpType].size()]; - curNode = tmp.first; - curContext = tmp.second; - } - } - -#ifdef ORIGINAL - vector newInputInfos = original_mutate(curNode, curContext, heat); -#else - vector newInputInfos = mutate(curNode, curContext, heat); -#endif - - for (InputInfo* newInputInfo : newInputInfos) { - newInputInfo->input_ = get_new_tree(originRoot, curNode, newInputInfo->input_); - - extract_struct(newInputInfo->input_); - - string tmpStr = newInputInfo->input_->to_string(); - - uint64_t h = hash(tmpStr); - if (sql_hash_.find(h) != sql_hash_.end()) { - delete newInputInfo; - continue; - } - sql_hash_.insert(h); - - IR* checkSql = check_sql(tmpStr); - if (checkSql == nullptr) { - delete newInputInfo; - continue; - } - else { - deep_delete(newInputInfo->input_); - newInputInfo->input_ = checkSql; - } - - res.push_back(newInputInfo); - } - } - } - - deep_delete(originRoot); - - mutateNumber_.push_back(res.size()); - seedCount_++; - - return res; -} - -vector Mutator::mutate(IR* root, IRContextS context, double heat) { - vector res; - - IRInfoManger* manger = IRInfo_[root->type_]; - vector indexes = manger->get_IRInfo_index(&context, heat); - - for (unsigned short int index : indexes) { - char flag = (rand() % 3) + 1; - - IR* left = nullptr; - IR* right = nullptr; - - IRInfomation* tmpIRInformation = manger->get_IRInfomation(index); - - InputInfo* newInputInfo = new InputInfo(); - newInputInfo->MutateIRType_ = root->type_; - newInputInfo->MutateIRInfoItem_ = index; - newInputInfo->MutateContext_ = context; - - if ((flag & 1) || ((root->left_ ? root->left_->type_ : IRTYPE::kNone) != tmpIRInformation->left_)) { - IR* tmp = get_ir_from_library(tmpIRInformation->left_); - left = deep_copy(tmp); - } - else { - left = deep_copy(root->left_); - } - - if ((flag & 2) || ((root->right_ ? root->right_->type_ : IRTYPE::kNone) != tmpIRInformation->right_)) { - IR* tmp = get_ir_from_library(tmpIRInformation->right_); - right = deep_copy(tmp); - } - else { - right = deep_copy(root->right_); - } - - IR* newIRTree = new IR(root, left, right); - - newIRTree->op_->prefix_ = tmpIRInformation->prefix_; - newIRTree->op_->middle_ = tmpIRInformation->middle_; - newIRTree->op_->suffix_ = tmpIRInformation->suffix_; - - newInputInfo->input_ = newIRTree; - - res.push_back(newInputInfo); - } - - return res; -} - -IR* Mutator::get_ir_from_library(IRTYPE type) { - if (type == IRTYPE::kNone) - return nullptr; - - if (IR_library_[type].empty()) { - fprintf(stderr, "ERROR: Lack IRTYPE : %d!!!\n", static_cast(type)); - assert(0); - } - - return IR_library_[type][rand() % (IR_library_[type].size())]; -} - -IR* Mutator::get_new_tree(IR* oldIRRoot, IR* curIR, IR* newIR) { - assert(oldIRRoot && curIR && newIR); - - IR* res = nullptr; - IR* left = nullptr; - IR* right = nullptr; - - if (oldIRRoot->left_ != nullptr) { - if (oldIRRoot->left_ == curIR) - left = newIR; - else - left = get_new_tree(oldIRRoot->left_, curIR, newIR); - } - - if (oldIRRoot->right_ != nullptr) { - if (oldIRRoot->right_ == curIR) - right = newIR; - else - right = get_new_tree(oldIRRoot->right_, curIR, newIR); - } - - res = new IR(oldIRRoot, left, right); - - return res; -} - -void Mutator::print_information(string outputPath) { - print_IRType_information(outputPath); - print_IRInfo_information(outputPath); - print_Mutate_number(outputPath); - -#ifdef ORIGINAL - print_OpInfo_information(outputPath); -#endif - - return; -} -void Mutator::print_IRType_information(string outputPath) { - ofstream outFileIRType(outputPath + "IRType_Information", ios::trunc); - - if (outFileIRType) { - for (auto& it : IRTypeCount_) { - IRTYPE curType = it.first; - pair& count = it.second; - - outFileIRType << "Current IRTYPE: " << to_string(curType) << endl; - outFileIRType << "\tSuccesses: " << to_string(count.first) << ", Failed: " << to_string(count.second) << ", Total: " << to_string(count.first + count.second) << endl << endl; - } - - outFileIRType.close(); - } - else { - cout << "ERROR: Can't Write IRType_Information File!!!" << endl; - } - - return; -} -void Mutator::print_IRInfo_information(string outputPath) { - ofstream outFileIRInfo(outputPath + "IRInfo_information", ios::trunc); - - if (outFileIRInfo) { - for (auto& it : IRInfo_) { - string info = it.second->print_IRInformation_status(); - outFileIRInfo << info << endl; - } - } - else { - cout << "ERROR: Can't Write IRInfo_information File!!!" << endl; - } - - return; -} -void Mutator::print_Mutate_number(string outputPath) { - ofstream outFileMutate(outputPath + "Mutate_number", ios::trunc); - - if (outFileMutate) { - for (unsigned short n : mutateNumber_) { - outFileMutate << n << endl; - } - } - else { - cout << "ERROR: Can't Write Mutate_number File!!!" << endl; - } - - return; -} -void Mutator::print_OpInfo_information(string outputPath) { - ofstream outFileIRInfo(outputPath + "OpInfo_information", ios::trunc); - - if (outFileIRInfo) { - pair OpReplace = { 0, 0 }; - pair OpInsert = { 0, 0 }; - pair OpDelete = { 0, 0 }; - - for (auto& it : OpInfo_) { - vector& chosenCounts = it.second->OpInfoChosenCount_; - vector& failedCounts = it.second->OpInfoFailedCount_; - - OpReplace.first += chosenCounts[0]; - OpReplace.second += failedCounts[0]; - - OpInsert.first += chosenCounts[1]; - OpInsert.second += failedCounts[1]; - - OpDelete.first += chosenCounts[2]; - OpDelete.second += failedCounts[2]; - - string info = it.second->print_OperatorInformation_status(); - outFileIRInfo << info << endl; - } - - outFileIRInfo << "Replace Operator\n\tTotal Chosen Number: " << to_string(OpReplace.first) << ", Total Failed Number: " << to_string(OpReplace.second) << ", Accuracy Rate: " << to_string(1 - static_cast(OpReplace.second) / OpReplace.first) << "%" << endl; - outFileIRInfo << "Insert Operator\n\tTotal Chosen Number: " << to_string(OpInsert.first) << ", Total Failed Number: " << to_string(OpInsert.second) << ", Accuracy Rate: " << to_string(1 - static_cast(OpInsert.second) / OpInsert.first) << "%" << endl; - outFileIRInfo << "Delete Operator\n\tTotal Chosen Number: " << to_string(OpDelete.first) << ", Total Failed Number: " << to_string(OpDelete.second) << ", Accuracy Rate: " << to_string(1 - static_cast(OpDelete.second) / OpDelete.first) << "%" << endl; - } - else { - cout << "ERROR: Can't Write OpInfo_information File!!!" << endl; - } - - return; -} - -unsigned int Mutator::get_duration_ms() { - chrono::time_point curTime = chrono::steady_clock::now(); - - return chrono::duration_cast(curTime - startTime).count(); -} -double Mutator::get_cur_heat() { - unsigned int duration = get_duration_ms(); - - return static_cast(1) / (static_cast(duration / TIMETHRESHOLD) + 1); -} -unsigned int Mutator::get_cur_reward() { - unsigned int duration = get_duration_ms(); - - return 1 + (duration / TIMETHRESHOLD) * REWARDINCREMENT; -} - -vector Mutator::original_mutate(IR* root, IRContextS context, double heat) { - vector res; - - OperatorManger* OpManger = OpInfo_[root->type_]; - vector indexes = OpManger->get_OpInfo_index(&context, heat); - - for (unsigned short int index : indexes) { - MutateOperator op = OpManger->get_operator(index); - IR* tmp = nullptr; - - switch (op) { - case MutateOperator::moReplace: { - tmp = strategy_replace(root); - break; - } - case MutateOperator::moInsert: { - tmp = strategy_insert(root); - break; - } - case MutateOperator::moDelete: { - tmp = strategy_delete(root); - break; - } - } - - if (tmp != nullptr) { - IRInfoManger* manger = IRInfo_[tmp->type_]; - manger->get_IRInfo_index(&context, get_cur_heat()); - - InputInfo* newInputInfo = new InputInfo(); - - newInputInfo->MutateIRType_ = root->type_; - newInputInfo->MutateIRInfoItem_ = manger->get_index_of_IRInfo(tmp); - newInputInfo->MutateContext_ = context; - newInputInfo->MutateOperatorItem_ = index; - - if (newInputInfo->MutateIRInfoItem_ != ERRORINDEX) { - manger->IRInfoChosenCount_[newInputInfo->MutateIRInfoItem_]++; - } - - newInputInfo->input_ = tmp; - - res.push_back(newInputInfo); - } - else { - OpManger->OpInfoFailedCount_[index]++; - OpManger->update_count(&context, index, false, get_cur_reward()); - } - } - - return res; -} - -IR* Mutator::strategy_delete(IR* root) { - IR* res = nullptr; - int flag = 0; - - if (root->left_ != nullptr && root->right_ != nullptr) { - flag = (rand() % 3) + 1; - } - else if (root->left_ != nullptr) { - flag = 1; - } - else if (root->right_ != nullptr) { - flag = 2; - } - else { - return nullptr; - } - - res = deep_copy(root); - - if ((flag & 1) == 1) { - deep_delete(res->left_); - res->left_ = nullptr; - } - - if ((flag & 2) == 2) { - deep_delete(res->right_); - res->right_ = nullptr; - } - - return res; -} -IR* Mutator::strategy_insert(IR* root) { - IRTYPE curType = root->type_; - - if (root->right_ == nullptr && root->left_ != nullptr) { - IRTYPE leftNodeType = root->left_->type_; - - for (int i = 0; i < 4; i++) { - IR* tmp = get_ir_from_library(curType); - - if (tmp != nullptr && tmp->left_ != nullptr && tmp->left_->type_ == leftNodeType && tmp->right_ != nullptr) { - IR* res = deep_copy(root); - res->right_ = deep_copy(tmp->right_); - - res->op_->prefix_ = tmp->op_->prefix_; - res->op_->middle_ = tmp->op_->middle_; - res->op_->suffix_ = tmp->op_->suffix_; - - return res; - } - } - } - else if (root->right_ != nullptr && root->left_ == nullptr) { - IRTYPE rightNodeType = root->right_->type_; - - for (int i = 0; i < 4; i++) { - IR* tmp = get_ir_from_library(curType); - - if (tmp != nullptr && tmp->right_ != nullptr && tmp->right_->type_ == rightNodeType && tmp->left_ != nullptr) { - IR* res = deep_copy(root); - res->left_ = deep_copy(tmp->left_); - - res->op_->prefix_ = tmp->op_->prefix_; - res->op_->middle_ = tmp->op_->middle_; - res->op_->suffix_ = tmp->op_->suffix_; - - return res; - } - } - } - else if (root->right_ == nullptr && root->left_ == nullptr) { - for (int i = 0; i < 4; i++) { - IR* tmp = get_ir_from_library(curType); - - if (tmp != nullptr && (tmp->left_ != nullptr || tmp->right_ != nullptr)) { - IR* res = deep_copy(root); - res->left_ = deep_copy(tmp->left_); - res->right_ = deep_copy(tmp->right_); - - res->op_->prefix_ = tmp->op_->prefix_; - res->op_->middle_ = tmp->op_->middle_; - res->op_->suffix_ = tmp->op_->suffix_; - - return res; - } - } - } - - return nullptr; -} -IR* Mutator::strategy_replace(IR* root) { - IR* res = nullptr; - int flag = 0; - - if (root->left_ != nullptr && root->right_ != nullptr) { - flag = (rand() % 3) + 1; - } - else if (root->left_ != nullptr) { - flag = 1; - } - else if (root->right_ != nullptr) { - flag = 2; - } - else { - return nullptr; - } - - res = deep_copy(root); - - if ((flag & 1) == 1) { - IR* tmpLeft = get_ir_from_library(res->left_->type_); - - if (tmpLeft != nullptr) { - deep_delete(res->left_); - res->left_ = deep_copy(tmpLeft); - } - } - - if ((flag & 2) == 2) { - IR* tmpRight = get_ir_from_library(res->right_->type_); - - if (tmpRight != nullptr) { - deep_delete(res->right_); - res->right_ = deep_copy(tmpRight); - } - } - - return res; -} - -IR* Mutator::check_sql(string& sql) { - IR* res = IR_parser(sql.c_str()); - - totalMutate_++; - if (res == nullptr) { - failedMutate_++; - } - - return res; -} - -//-----------------------------IRInfomation----------------------------- -IRInfomation::IRInfomation(int prefix, int left, int middle, int right, int suffix) { - prefix_ = static_cast(prefix); - left_ = static_cast(left); - middle_ = static_cast(middle); - right_ = static_cast(right); - suffix_ = static_cast(suffix); - - return; -} -IRInfomation::IRInfomation(IR* root) { - prefix_ = root->op_->prefix_; - left_ = root->left_ != nullptr ? root->left_->type_ : IRTYPE::kNone; - middle_ = root->op_->middle_; - right_ = root->right_ != nullptr ? root->right_->type_ : IRTYPE::kNone; - suffix_ = root->op_->suffix_; - - return; -} - -bool IRInfomation::operator!=(IRInfomation* info) { - if (info->prefix_ != prefix_) { - return true; - } - - if (info->left_ != left_) { - return true; - } - - if (info->middle_ != middle_) { - return true; - } - - if (info->right_ != right_) { - return true; - } - - if (info->suffix_ != suffix_) { - return true; - } - - return false; -} - -//-----------------------------IRInfoManger----------------------------- -IRInfoManger::IRInfoManger() {} -IRInfoManger::~IRInfoManger() { - for (IRInfomation* info : IRInfomation_) { - delete info; - } - - return; -} - -void IRInfoManger::create_new_context(IRContextS* context) { - uint64_t index = *reinterpret_cast(context); - - assert(contextDependentCount_.find(index) == contextDependentCount_.end()); - - for (int i = 0; i < IRInfomation_.size(); i++) { - contextDependentCount_[index].push_back({0, 0}); - } - - return; -} - -void IRInfoManger::update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward) { - uint64_t index = *reinterpret_cast(context); - - assert(contextDependentCount_.find(index) != contextDependentCount_.end()); - - if (item == ERRORINDEX) { - return; - } - - if (hasNewCoverage == true) { - contextDependentCount_[index][item].first += reward; - } - else { - contextDependentCount_[index][item].second += reward; - } - - return; -} - -void IRInfoManger::add_IRInfomation(IRInfomation* info) { - IRInfomation_.push_back(info); - IRInfoChosenCount_.push_back(0); - return; -} -IRInfomation* IRInfoManger::get_IRInfomation(unsigned short int index) { - assert(index < IRInfomation_.size() && index >= 0); - IRInfoChosenCount_[index]++; - return IRInfomation_[index]; -} - -#ifdef BALANCE -vector IRInfoManger::get_IRInfo_index(IRContextS* context, double heat) { - vector res; - uint64_t index = *reinterpret_cast(context); - - if (contextDependentCount_.find(index) == contextDependentCount_.end()) { - create_new_context(context); - } - - for (int i = 0; i < MUTATENUMBER; i++) { - double randomNumber = get_random_double(0, 1); - if (randomNumber < heat) { - res.push_back(rand() % IRInfomation_.size()); - } - else { - int maxIndex = ERRORINDEX; - double maxExpect = 0.0; - vector>& counts = contextDependentCount_[index]; - - for (int i = 0; i < counts.size(); i++) { - unsigned int totalNumber = counts[i].first + counts[i].second; - if (totalNumber <= IRINFOUPDATETHRESHOLD) { - continue; - } - - double expect = counts[i].first / totalNumber; - if (expect > maxExpect) { - maxIndex = i; - maxExpect = expect; - } - } - - if (maxIndex != ERRORINDEX) { - res.push_back(maxIndex); - } - else { - res.push_back(rand() % IRInfomation_.size()); - } - } - } - - return res; -} -#else -vector IRInfoManger::get_IRInfo_index(IRContextS* context, double heat) { - vector res; - vector skip; - uint64_t index = *reinterpret_cast(context); - - if (contextDependentCount_.find(index) == contextDependentCount_.end()) { - create_new_context(context); - } - - unsigned short int maxExpectIndex = ERRORINDEX; - double maxExpect = 0; - - vector>& curContextCount = contextDependentCount_[index]; - int mutateNumber = curContextCount.size(); - - for (int i = 0; i < curContextCount.size(); i++) { - pair& count = curContextCount[i]; - - unsigned int chosenNumber = count.first + count.second; - if (chosenNumber > IRINFOUPDATETHRESHOLD) { - double expect = static_cast(count.first) / chosenNumber; - - if (expect > maxExpect) { - maxExpectIndex = i; - maxExpect = expect; - } - } - - double tmp = get_random_double(0, 1); - if (chosenNumber <= IRINFOUPDATETHRESHOLD || tmp < heat) { - res.push_back(i); - mutateNumber--; - } - else { - skip.push_back(i); - } - } - - if (maxExpectIndex == ERRORINDEX) { - for (unsigned short int i : skip) { - res.push_back(i); - } - } - else { - while (mutateNumber > 0) { - res.push_back(maxExpectIndex); - mutateNumber--; - } - } - - return res; -} -#endif - -unsigned short int IRInfoManger::get_index_of_IRInfo(IR* root) { - int res = ERRORINDEX; - IRInfomation curIRInfo(root); - - for (int i = 0; i < IRInfomation_.size(); i++) { - if (*IRInfomation_[i] != &curIRInfo) { - continue; - } - - res = i; - break; - } - - return res; -} - -string IRInfoManger::print_IRInformation_status() { - unsigned long totalSuccessCount = 0; - unsigned long totalFailedCount = 0; - - string res = "Current IRTYPE: " + to_string(curIRType_) + "\n"; - - for (int i = 0; i < IRInfomation_.size(); i++) { - unsigned long successCount = 0; - unsigned long failedCount = 0; - IRInfomation* tmp = IRInfomation_[i]; - - res += "--IRInfo " + to_string(i) + ": " + to_string(tmp->prefix_) + " " + to_string(tmp->left_) + " " + to_string(tmp->middle_) + " " + to_string(tmp->right_) + " " + to_string(tmp->suffix_) + ":\n"; - res += "--Total Chosen Number: " + to_string(IRInfoChosenCount_[i]) + "\n"; - - for (auto& it : contextDependentCount_) { - uint64_t context = it.first; - pair& count = it.second[i]; - - successCount += count.first; - totalSuccessCount += count.first; - failedCount += count.second; - totalFailedCount += count.second; - - res += "\tCurrent Context: " + to_string(context) + ", Successes: " + to_string(count.first) + ", Failed: " + to_string(count.second) + ", Total: " + to_string(count.first + count.second) + "\n"; - } - - res += "--Successes: " + to_string(successCount) + ", Failed: " + to_string(failedCount) + ", Total: " + to_string(successCount + failedCount) + "\n"; - } - - res += "Total Successes: " + to_string(totalSuccessCount) + ", Total Failed: " + to_string(totalFailedCount) + ", Total: " + to_string(totalSuccessCount + totalFailedCount) + "\n\n"; - - return res; -} - -//-----------------------------InputInfo----------------------------- -InputInfo::InputInfo() {} -InputInfo::~InputInfo() { - deep_delete(input_); - return; -} - -//-----------------------------OperatorManger----------------------------- -OperatorManger::OperatorManger() { - OperatorInfomation_ = { MutateOperator::moReplace, MutateOperator::moInsert, MutateOperator::moDelete }; - OpInfoChosenCount_ = { 0, 0, 0 }; - OpInfoFailedCount_ = { 0, 0, 0 }; - - return; -} -OperatorManger::~OperatorManger() {} - -void OperatorManger::create_new_context(IRContextS* context) { - uint64_t index = *reinterpret_cast(context); - - assert(contextDependentCount_.find(index) == contextDependentCount_.end()); - - for (int i = 0; i < OperatorInfomation_.size(); i++) { - contextDependentCount_[index].push_back({ 0, 0 }); - } - - return; -} -vector OperatorManger::get_OpInfo_index(IRContextS* context, double heat) { - vector res; - vector skip; - - IRContextS OpContext = *context; - OpContext.parentIRItem_ = ERRORINDEX; - - uint64_t index = *reinterpret_cast(&OpContext); - - if (contextDependentCount_.find(index) == contextDependentCount_.end()) { - create_new_context(&OpContext); - } - - unsigned short int maxExpectIndex = ERRORINDEX; - double maxExpect = 0; - - vector>& curContextCount = contextDependentCount_[index]; - int mutateNumber = curContextCount.size(); - - for (int i = 0; i < curContextCount.size(); i++) { - pair& count = curContextCount[i]; - - unsigned int chosenNumber = count.first + count.second; - if (chosenNumber > IRINFOUPDATETHRESHOLD) { - double expect = static_cast(count.first) / (count.first + count.second); - - if (expect > maxExpect) { - maxExpectIndex = i; - maxExpect = expect; - } - } - - double tmp = get_random_double(0, 1); - if (chosenNumber < IRINFOUPDATETHRESHOLD || tmp < heat) { - res.push_back(i); - mutateNumber--; - } - else { - skip.push_back(i); - } - } - - if (maxExpectIndex == ERRORINDEX) { - for (unsigned short int i : skip) { - res.push_back(i); - } - } - else { - while (mutateNumber > 0) { - res.push_back(maxExpectIndex); - mutateNumber--; - } - } - - return res; -} -MutateOperator OperatorManger::get_operator(unsigned short int index) { - assert(index < OperatorInfomation_.size() && index >= 0); - OpInfoChosenCount_[index]++; - return OperatorInfomation_[index]; -} - -void OperatorManger::update_count(IRContextS* context, unsigned short int item, bool hasNewCoverage, unsigned int reward) { - IRContextS OpContext = *context; - OpContext.parentIRItem_ = ERRORINDEX; - - uint64_t index = *reinterpret_cast(&OpContext); - - assert(contextDependentCount_.find(index) != contextDependentCount_.end()); - - if (item == ERRORINDEX) { - return; - } - - if (hasNewCoverage == true) { - contextDependentCount_[index][item].first += reward; - } - else { - contextDependentCount_[index][item].second += reward; - } - - return; -} - -string OperatorManger::print_OperatorInformation_status() { - unsigned long totalSuccessCount = 0; - unsigned long totalFailedCount = 0; - - string res = "Current IRTYPE: " + to_string(curIRType_) + "\n"; - - for (int i = 0; i < OperatorInfomation_.size(); i++) { - unsigned long successCount = 0; - unsigned long failedCount = 0; - MutateOperator op = OperatorInfomation_[i]; - - string OpStr = ""; - switch (op) { - case MutateOperator::moReplace: { - OpStr += "REPLACE"; - break; - } - case MutateOperator::moInsert: { - OpStr += "INSERT"; - break; - } - case MutateOperator::moDelete: { - OpStr += "DELETE"; - break; - } - } - - res += "--Operator " + OpStr + ":\n"; - res += "--Total Chosen Number: " + to_string(OpInfoChosenCount_[i]) + ", " + "Mutate Failed: " + to_string(OpInfoFailedCount_[i]) + "\n"; - - for (auto& it : contextDependentCount_) { - uint64_t context = it.first; - pair& count = it.second[i]; - - successCount += count.first; - totalSuccessCount += count.first; - failedCount += count.second; - totalFailedCount += count.second; - - res += "\tCurrent Context: " + to_string(context) + ", Successes: " + to_string(count.first) + ", Failed: " + to_string(count.second) + ", Total: " + to_string(count.first + count.second) + "\n"; - } - - res += "--Successes: " + to_string(successCount) + ", Failed: " + to_string(failedCount) + ", Total: " + to_string(successCount + failedCount) + "\n"; - } - - res += "Total Successes: " + to_string(totalSuccessCount) + ", Total Failed: " + to_string(totalFailedCount) + ", Total: " + to_string(totalSuccessCount + totalFailedCount) + "\n\n"; - - return res; -} diff --git a/src/tool.cpp b/src/tool.cpp deleted file mode 100755 index 67baf7f..0000000 --- a/src/tool.cpp +++ /dev/null @@ -1,1122 +0,0 @@ -#include "../include/instantiate.h" - -using namespace std; - -//-----------------------------Column----------------------------- -Column::Column(name_t name, ColumnType type): identifierName_(name), columnType_(type) {} -Column::Column(Column* column) { - notNull_ = column->notNull_; - hasDefault_ = column->hasDefault_; - isVisible_ = column->isVisible_; - identifierName_ = column->identifierName_; - duplicated_ = column->duplicated_; - columnType_ = column->columnType_; - - return; -} - -void Column::instantiate() { - return; -} - -//-----------------------------Index----------------------------- -Index::Index(name_t name): identifierName_(name) {} - -//-----------------------------Constraint----------------------------- -Constraint::Constraint(name_t name, ConstraintType type): identifierName_(name), constraintType_(type) {} - -//-----------------------------Table----------------------------- -Table::Table(name_t name, IdentifierType identifierType, SelectStmtInfo* inSelectStmtInfo) : identifierName_(name), inSelectStmtInfo_(inSelectStmtInfo), identifierType_(identifierType) { - for (int i = 0; i < RESERVEDCOLUMNNAME; i++) { - acceColumnNames_.push_back(i); - } - - random_device rd; - mt19937 g(rd()); - - shuffle(acceColumnNames_.begin(), acceColumnNames_.end(), g); - - return; -} -Table::Table(Table* otherTable, SelectStmtInfo* inSelectStmtInfo) : identifierName_(otherTable->identifierName_), inSelectStmtInfo_(inSelectStmtInfo), identifierType_(otherTable->identifierType_) { - acceColumnNames_ = otherTable->acceColumnNames_; - - for (Column* c : otherTable->columns_) { - add_column(new Column(c)); - } - - return; -} -Table::~Table() { - for (Column* c : columns_) { - delete c; - } - - for (Index* i : indexes_) { - delete i; - } - - for (Constraint* c : constraints_) { - delete c; - } - - return; -} - -bool Table::check_drop_table() { - if (!refFromOtherColumns_.empty()) { - return false; - } - - return false; -} -bool Table::exist_duplicated_column() { - for (Column* c : columns_) { - if (c->duplicated_ == ColumnStatus::csDuplication) { - return true; - } - } - - return false; -} -void Table::update_duplicationInfo(vector& duplicationInfo) { - assert(duplicationInfo.size() == COLUMNNAMEMAX); - int size = columns_.size(); - - for (int i = 0; i < size; i++) { - duplicationInfo[columns_[i]->identifierName_]++; - } - - return; -} -void Table::update_duplicatedColumns(vector& duplicationInfo) { - assert(duplicationInfo.size() == COLUMNNAMEMAX); - - for (Column* c : columns_) { - assert(c->identifierName_ < COLUMNNAMEMAX); - if (duplicationInfo[c->identifierName_] > 1) { - c->duplicated_ = ColumnStatus::csDuplication; - } - else if (duplicationInfo[c->identifierName_] == 1) { - c->duplicated_ = ColumnStatus::csNormal; - } - } - - return; -} - -bool Table::column_drop_check(Column* column) { - vector indexes = get_index(column); - vector constraints = get_constraint(column); - - if (find(columns_.begin(), columns_.end(), column) == columns_.end()) { - return false; - } - - for (Index* index : indexes) { - if (index->columns_[column] == IndexType::itFunctional) { - return false; - } - } - - for (Constraint* constraint : constraints) { - if (constraint->columns_[column] == IndexType::itFunctional || constraint->constraintType_ == ConstraintType::ctForeignKey || constraint->constraintType_ == ConstraintType::ctCheck) { - return false; - } - } - - return true; -} -Column* Table::get_column() { - if (columns_.empty()) { - fprintf(stderr, "ERROR: Empty Table!!!\n"); - assert(0); - } - - return columns_[rand() % columns_.size()]; -} -Column* Table::get_column(ColumnType type) { - vector tmp; - - for (Column* c : columns_) { - if (c->columnType_ == type) { - tmp.push_back(c); - } - } - - if (tmp.empty()) { - return nullptr; - } - - return tmp[rand() % tmp.size()]; -} -name_t Table::get_acce_column_name() { - if (acceColumnNames_.empty()) { - return 0; - } - - return acceColumnNames_[0]; -} -vector Table::get_column_seq() { - int size = columns_.size(); - vector tmp; - - for (int i = 0; i < size; i++) { - tmp.push_back(columns_[i]); - } - - random_device rd; - mt19937 g(rd()); - - shuffle(tmp.begin(), tmp.end(), g); - - return tmp; -} -void Table::add_column_first(Column* column) { - assert(column != nullptr); - remove_column_name(column->identifierName_); - column->parentTable_ = this; - - columns_.insert(columns_.begin(), column); - - return; -} -bool Table::add_column(Column* column, Column* afterColumn) { - assert(column != nullptr); - remove_column_name(column->identifierName_); - column->parentTable_ = this; - - return move_column(column, afterColumn); -} -void Table::move_column_first(Column* column) { - auto it = find(columns_.begin(), columns_.end(), column); - assert(it != columns_.end()); - - columns_.erase(it); - columns_.insert(columns_.begin(), column); - - return; -} -bool Table::move_column(Column* column, Column* afterColumn) { - assert(column != afterColumn); - - auto it1 = find(columns_.begin(), columns_.end(), column); - auto it2 = find(columns_.begin(), columns_.end(), afterColumn); - - assert(afterColumn == nullptr || it2 != columns_.end()); - - if (it1 != columns_.end()) { - columns_.erase(it1); - } - - if (afterColumn == nullptr) { - columns_.push_back(column); - } - else { - auto it2 = find(columns_.begin(), columns_.end(), afterColumn); - columns_.insert(it2 + 1, column); - } - - return true; -} -bool Table::drop_column(Column* column) { - if (!column_drop_check(column)) { - return false; - } - - auto it = find(columns_.begin(), columns_.end(), column); - - add_column_name(column->identifierName_); - - drop_index(column); - drop_constraint(column); - - delete column; - columns_.erase(it); - - return true; -} - -void Table::column_rename(Column* column, name_t oldName, name_t newName) { - column->identifierName_ = newName; - - remove_column_name(newName); - add_column_name(oldName); - - return; -} - -Index* Table::get_index() { - if (indexes_.empty()) { - return nullptr; - } - - return indexes_[rand() % indexes_.size()]; -} -vector Table::get_index(Column* column) { - vector tmp; - - for (Index* index : indexes_) { - if (index->columns_.find(column) != index->columns_.end()) { - tmp.push_back(index); - } - } - - return tmp; -} -bool Table::add_index(Index* index) { - if (find(indexes_.begin(), indexes_.end(), index) != indexes_.end()) { - return false; - } - - indexes_.push_back(index); - return true; -} -bool Table::drop_index(Index* index) { - if (!index_drop_check(index)) { - return false; - } - - auto it = find(indexes_.begin(), indexes_.end(), index); - - if (index->constraint_ != nullptr) { - assert(index->constraint_->index_ == index); - index->constraint_->index_ = nullptr; - drop_constraint(index->constraint_); - } - - indexes_.erase(it); - delete index; - - return true; -} - -Constraint* Table::get_constraint() { - if (constraints_.empty()) { - return nullptr; - } - - return constraints_[rand() % constraints_.size()]; -} -vector Table::get_constraint(Column* column) { - vector tmp; - - for (Constraint* constraint : constraints_) { - if (constraint->columns_.find(column) != constraint->columns_.end()) { - tmp.push_back(constraint); - } - } - - return tmp; -} -bool Table::add_constraint(Constraint* constraint, Index* index) { - if (find(constraints_.begin(), constraints_.end(), constraint) != constraints_.end()) { - return false; - } - - constraint->index_ = index; - constraints_.push_back(constraint); - - if (index != nullptr) { - index->constraint_ = constraint; - add_index(index); - } - - if (constraint->constraintType_ == ConstraintType::ctForeignKey) { - for (auto& it : constraint->refToOtherColumns_) { - Column* otherTableColumn = it.first; - for (Column* curTableColumn : it.second) { - curTableColumn->parentTable_->set_references(curTableColumn, otherTableColumn); - } - } - } - - if (constraint->constraintType_ == ConstraintType::ctPrimaryKey) { - hasPrimaryKey_ = true; - } - - return true; -} -bool Table::drop_constraint(Constraint* constraint) { - if (!constraint_drop_check(constraint)) { - return false; - } - - auto it = find(constraints_.begin(), constraints_.end(), constraint); - - if (constraint->index_ != nullptr) { - assert(constraint->index_->constraint_ == constraint); - constraint->index_->constraint_ = nullptr; - drop_index(constraint->index_); - } - - if (constraint->constraintType_ == ConstraintType::ctForeignKey) { - for (auto& it : constraint->refToOtherColumns_) { - Column* otherTableColumn = it.first; - for (Column* curTableColumn : it.second) { - curTableColumn->parentTable_->remove_references(curTableColumn, otherTableColumn); - } - } - } - - if (constraint->constraintType_ == ConstraintType::ctPrimaryKey) { - hasPrimaryKey_ = false; - } - - delete constraint; - constraints_.erase(it); - - return true; -} -bool Table::set_references(Column* curTableColumn, Column* otherTableColumn) { - if (find(columns_.begin(), columns_.end(), curTableColumn) == columns_.end()) { - return false; - } - - if (refFromOtherColumns_.find(curTableColumn) != refFromOtherColumns_.end() && refFromOtherColumns_[curTableColumn].find(otherTableColumn) != refFromOtherColumns_[curTableColumn].end()) { - refFromOtherColumns_[curTableColumn][otherTableColumn] += 1; - } - else { - refFromOtherColumns_[curTableColumn][otherTableColumn] = 1; - } - - return true; -} -bool Table::remove_references(Column* curTableColumn, Column* otherTableColumn) { - if (find(columns_.begin(), columns_.end(), curTableColumn) == columns_.end()) { - return false; - } - - if (refFromOtherColumns_.find(curTableColumn) != refFromOtherColumns_.end() && refFromOtherColumns_[curTableColumn].find(otherTableColumn) != refFromOtherColumns_[curTableColumn].end()) { - refFromOtherColumns_[curTableColumn][otherTableColumn] -= 1; - - if (refFromOtherColumns_[curTableColumn][otherTableColumn] <= 0) { - auto it1 = refFromOtherColumns_[curTableColumn].find(otherTableColumn); - refFromOtherColumns_[curTableColumn].erase(it1); - - if (refFromOtherColumns_[curTableColumn].empty()) { - auto it2 = refFromOtherColumns_.find(curTableColumn); - refFromOtherColumns_.erase(it2); - } - } - } - else { - return false; - } - - return true; -} - - -bool Table::remove_column_name(name_t name) { - auto it = find(acceColumnNames_.begin(), acceColumnNames_.end(), name); - - if (it == acceColumnNames_.end()) { - return false; - } - - acceColumnNames_.erase(it); - - return true; -} -bool Table::add_column_name(name_t name) { - auto it = find(acceColumnNames_.begin(), acceColumnNames_.end(), name); - if (it == acceColumnNames_.end()) { - acceColumnNames_.push_back(name); - return true; - } - - return false; -} -void Table::drop_index(Column* column) { - vector waitForDrop; - vector indexes = get_index(column); - - for (Index* index : indexes) { - auto it = index->columns_.find(column); - index->columns_.erase(it); - - if (index->columns_.empty()) { - waitForDrop.push_back(index); - } - } - - for (Index* index : waitForDrop) { - drop_index(index); - } - - return; -} -void Table::drop_constraint(Column* column) { - vector waitForDrop; - vector constraints = get_constraint(column); - - for (Constraint* constraint : constraints) { - auto it = constraint->columns_.find(column); - constraint->columns_.erase(column); - - if (constraint->columns_.empty()) { - waitForDrop.push_back(constraint); - } - } - - for (Constraint* constraint : constraints_) { - drop_constraint(constraint); - } - - return; -} - -bool Table::index_drop_check(Index* index) { - if (find(indexes_.begin(), indexes_.end(), index) == indexes_.end()) { - return false; - } - - for (auto& it : index->columns_) { - if (refFromOtherColumns_.find(it.first) != refFromOtherColumns_.end()) { - return false; - } - } - - return true; -} - -bool Table::constraint_drop_check(Constraint* constraint) { - if (find(constraints_.begin(), constraints_.end(), constraint) == constraints_.end()) { - return false; - } - - return true; -} - -//-----------------------------SelectStmtInfo----------------------------- -SelectStmtInfo::SelectStmtInfo(StmtLocation location, int rowNumber, int columnNumber) : location_(location), rowNumber_(rowNumber), columnNumber_(columnNumber) {} -SelectStmtInfo::~SelectStmtInfo() { - clear_local_info(); - clear_cte(); - - return; -} - -bool SelectStmtInfo::is_duplicated_table(Table* table) { - for (Table* t : usedTables_) { - if (t->identifierName_ == table->identifierName_) { - return true; - } - } - - return false; -} -bool SelectStmtInfo::exist_duplicated_column(vector& v1, vector& v2) { - vector bitmap = vector(COLUMNNAMEMAX, 0); - - for (Column* c : v1) { - bitmap[c->identifierName_]++; - } - - for (Column* c : v2) { - bitmap[c->identifierName_]++; - } - - for (int i : bitmap) { - if (i > 1) { - return true; - } - } - - return false; -} -bool SelectStmtInfo::has_column_limit() { - return columnNumber_ != DEFAULTCOLUMNNUMBER; -} -bool SelectStmtInfo::has_row_limit() { - return rowNumber_ != DEFAULTROWNUMBER; -} - -void SelectStmtInfo::add_used_table(Table* table) { - table->update_duplicationInfo(duplicationInfo_); - usedTables_.push_back(table); - - return; -} -void SelectStmtInfo::clear_local_info() { - for (Table* t : usedTables_) { - delete t; - } - - for (int i = 0; i < COLUMNNAMEMAX; i++) { - duplicationInfo_[i] = 0; - } - - hasAggregate = false; - - usedTables_.clear(); - usedInnerColumns_.clear(); - acceColumns_.clear(); - windowStatusRecord_.clear(); - - return; -} -void SelectStmtInfo::clear_cte() { - for (auto it = innerCteTables_.begin(); it != innerCteTables_.end(); it++) { - Table* cte = *it; - delete cte; - } - - innerCteTables_.clear(); - - return; -} - -void SelectStmtInfo::update_acceColumns() { - acceColumns_.clear(); - map> tmp; - - for (Table* t : usedTables_) { - t->update_duplicatedColumns(duplicationInfo_); - - for (Column* c : t->columns_) { - tmp[c->identifierName_].push_back(c); - } - } - - for (Column* c : outReferences_) { - if (tmp.find(c->identifierName_) == tmp.end()) { - tmp[c->identifierName_].push_back(c); - } - else { - Column* cc = tmp[c->identifierName_][0]; - - if (cc->parentTable_->inSelectStmtInfo_ != this) { - tmp[c->identifierName_].push_back(c); - } - } - } - - for (auto& it : tmp) { - for (Column* c : it.second) { - acceColumns_.push_back(c); - } - } - - return; -} -void SelectStmtInfo::update_acceColumns(vector& usedTables, vector& duplicationInfo) { - acceColumns_.clear(); - map> tmp; - - for (Table* t : usedTables) { - t->update_duplicatedColumns(duplicationInfo); - - for (Column* c: t->columns_) { - tmp[c->identifierName_].push_back(c); - } - } - - for (Column* c : outReferences_) { - if (tmp.find(c->identifierName_) == tmp.end()) { - tmp[c->identifierName_].push_back(c); - } - else { - Column* cc = tmp[c->identifierName_][0]; - - if (cc->parentTable_->inSelectStmtInfo_ != this) { - tmp[c->identifierName_].push_back(c); - } - } - } - - for (auto& it : tmp) { - for (Column* c : it.second) { - acceColumns_.push_back(c); - } - } - - return; -} - -void SelectStmtInfo::add_usedInnerColumns(Column* column) { - if (find(usedInnerColumns_.begin(), usedInnerColumns_.end(), column) == usedInnerColumns_.end()) { - usedInnerColumns_.push_back(column); - } - - return; -} -void SelectStmtInfo::add_usedOutColumns(Column* column) { - if (find(usedOutColumns_.begin(), usedOutColumns_.end(), column) == usedOutColumns_.end()) { - usedOutColumns_.push_back(column); - } - - return; -} -void SelectStmtInfo::add_out_usedColumns(vector& usedColumns) { - for (Column* c : usedColumns) { - if (c->parentTable_->inSelectStmtInfo_ != this) { - add_usedOutColumns(c); - } - } - - return; -} -void SelectStmtInfo::add_all_usedColumns(vector& usedColumns) { - for (Column* c : usedColumns) { - if (c->parentTable_->inSelectStmtInfo_ == this) { - add_usedInnerColumns(c); - } - else { - add_usedOutColumns(c); - } - } - - return; -} - -//-----------------------------GlobalStatusManger----------------------------- -GlobalStatusManger::~GlobalStatusManger() { - for (Table* t : globalTables_) { - delete t; - } - - return; -} - -void GlobalStatusManger::reset_status() { - totalTableName_ = 0; - totalViewName_ = 0; - totalWindowName_ = 0; - totalIndexName_ = 0; - totalConstraintName_ = 0; - - assert(selectInfoStack_.empty()); - - for (Table* t : globalTables_) { - delete t; - } - - globalTables_.clear(); - - return; -} - -void GlobalStatusManger::push_selectInfo(StmtLocation location, int rowNumber, int columnNumber) { - SelectStmtInfo* info = new SelectStmtInfo(location, rowNumber, columnNumber); - SelectStmtInfo* preInfo = get_cur_selectInfo(); - - if (preInfo != nullptr) { - info->outCteTables_ = preInfo->outCteTables_; - for (Table* t : preInfo->innerCteTables_) { - info->outCteTables_.push_back(t); - } - - info->outReferences_ = preInfo->acceColumns_; - - if (location == StmtLocation::slRecursiveCTE) { - info->recursiveCteName_ = preInfo->recursiveCteName_; - } - } - - selectInfoStack_.push(info); - - return; -} -void GlobalStatusManger::pop_selectInfo() { - SelectStmtInfo* info = get_cur_selectInfo(); - pop_cur_selectInfo(); - SelectStmtInfo* preinfo = get_cur_selectInfo(); - - if (preinfo != nullptr && info != nullptr) { - if (find(ignoreInnerUsedColumns_.begin(), ignoreInnerUsedColumns_.end(), info->location_) != ignoreInnerUsedColumns_.end()) { - preinfo->add_out_usedColumns(info->usedOutColumns_); - } - else { - preinfo->add_all_usedColumns(info->usedOutColumns_); - } - } - - if (info != nullptr) { - delete info; - } - - return; -} - -SelectStmtInfo* GlobalStatusManger::get_cur_selectInfo() { - if (selectInfoStack_.empty()) { - return nullptr; - } - - return selectInfoStack_.top(); -} -void GlobalStatusManger::pop_cur_selectInfo() { - if (selectInfoStack_.empty()) { - fprintf(stderr, "ERROR: Pop Empty Stack\n"); - assert(0); - } - - selectInfoStack_.pop(); - - return; -} - -int GlobalStatusManger::get_acce_table_number() { - int res = 0; - SelectStmtInfo* info = get_cur_selectInfo(); - - res += globalTables_.size() + info->outCteTables_.size() + info->innerCteTables_.size(); - - return res; -} -Table* GlobalStatusManger::get_acce_table(int index) { - Table* res = nullptr; - SelectStmtInfo* info = get_cur_selectInfo(); - - if (index < globalTables_.size()) { - res = globalTables_[index]; - } - else if(index - globalTables_.size() < info->outCteTables_.size()) { - res = info->outCteTables_[index - globalTables_.size()]; - } - else { - res = info->innerCteTables_[index - globalTables_.size() - info->outCteTables_.size()]; - } - - assert(res != nullptr); - - return res; -} -vector GlobalStatusManger::get_acce_table(IdentifierType type) { - assert(type == IdentifierType::iTable || type == IdentifierType::iView); - - vector res; - - for (Table* table : globalTables_) { - if (table->identifierType_ == type) { - res.push_back(table); - } - } - - return res; -} - -name_t GlobalStatusManger::get_new_table_name() { - return totalTableName_++; -} -name_t GlobalStatusManger::get_new_view_name() { - return totalViewName_++; -} -name_t GlobalStatusManger::get_new_window_name() { - return totalWindowName_++; -} -name_t GlobalStatusManger::get_new_index_name() { - return totalIndexName_++; -} -name_t GlobalStatusManger::get_new_constraint_name() { - return totalConstraintName_++; -} - -bool GlobalStatusManger::add_table(Table* table) { - if (table == nullptr || find(globalTables_.begin(), globalTables_.end(), table) != globalTables_.end()) { - return false; - } - - globalTables_.push_back(table); - - return true; -} -bool GlobalStatusManger::drop_table(Table* table) { - auto it = find(globalTables_.begin(), globalTables_.end(), table); - - if (it == globalTables_.end()) { - return false; - } - - globalTables_.erase(it); - delete table; - - return true; -} -bool GlobalStatusManger::drop_table(name_t name, IdentifierType type) { - Table* tmp = nullptr; - - for (Table* table : globalTables_) { - if (table->identifierName_ == name && table->identifierType_ == type) { - tmp = table; - break; - } - } - - if (tmp != nullptr) { - return drop_table(tmp); - } - - return true; -} - -//-----------------------------IRTrim----------------------------- -IRTrim::IRTrim(Instantiator* instantiator): instantiator_(instantiator) { - instantiate_simple_limit(); - instantiate_simple_column_list(); - instantiate_simple_alias(); - instantiate_simple_expr_root(); - instantiate_simple_expr_root_true(); - instantiate_simple_expr_root_list(); - instantiate_simple_simple_select_item_list(); - instantiate_simple_window_spec(); - instantiate_simple_index_name(); - instantiate_simple_constraint_name(); - instantiate_simple_key_part(); - instantiate_simple_key_part_list(); - instantiate_simple_table_element(); - instantiate_simple_values(); - - return; -} -IRTrim::~IRTrim() { - for (IR* ir : simpleIR_) { - if (ir != nullptr) { - deep_delete(ir); - } - } - - return; -} - -void IRTrim::instantiate_simple_limit() { - IR* iconst = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); - IR* limit_options = new IR(IRTYPE::kLimitOptions, OP0(), iconst, nullptr); - IR* limit_clause = new IR(IRTYPE::kLimitClause, OP3(TERMINAL::tLimit, TERMINAL::tEmpty, TERMINAL::tEmpty), limit_options, nullptr); - - simple_limit_ = limit_clause; - simpleIR_.push_back(simple_limit_); - - return; -} -void IRTrim::instantiate_simple_column_list() { - IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), ident, nullptr); - IR* column_list = new IR(IRTYPE::kColumnList, OP0(), column_name, nullptr); - - simple_column_list_ = column_list; - simpleIR_.push_back(simple_column_list_); - - return; -} -void IRTrim::instantiate_simple_alias() { - IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* alias = new IR(IRTYPE::kAlias, OP0(), ident, nullptr); - - simple_alias_ = alias; - simpleIR_.push_back(simple_alias_); - - return; -} -void IRTrim::instantiate_simple_expr_root() { - IR* iconst = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); - IR* simple_expr = new IR(IRTYPE::kSimpleExpr, OP0(), iconst, nullptr); - IR* bit_expr = new IR(IRTYPE::kBitExpr, OP0(), simple_expr, nullptr); - IR* predicate = new IR(IRTYPE::kPredicate, OP0(), bit_expr, nullptr); - IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), predicate, nullptr); - IR* expr = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); - IR* expr_root = new IR(IRTYPE::kExprRoot, OP0(), expr, nullptr); - - iconst->long_val_ = 1; - - simple_expr_root_ = expr_root; - simpleIR_.push_back(simple_expr_root_); - - return; -} -void IRTrim::instantiate_simple_expr_root_true() { - IR* literal = new IR(IRTYPE::kLiteral, OP3(TERMINAL::tTrue, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - IR* simple_expr = new IR(IRTYPE::kSimpleExpr, OP0(), literal, nullptr); - IR* bit_expr = new IR(IRTYPE::kBitExpr, OP0(), simple_expr, nullptr); - IR* predicate = new IR(IRTYPE::kPredicate, OP0(), bit_expr, nullptr); - IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), predicate, nullptr); - IR* expr = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); - IR* expr_root = new IR(IRTYPE::kExprRoot, OP0(), expr, nullptr); - - simple_expr_root_true_ = expr_root; - simpleIR_.push_back(simple_expr_root_true_); - - return; -} -void IRTrim::instantiate_simple_expr_root_list() { - IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); - IR* columnref = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), column_name, nullptr); - IR* simple_expr = new IR(IRTYPE::kSimpleExpr, OP0(), columnref, nullptr); - IR* bit_expr = new IR(IRTYPE::kBitExpr, OP0(), simple_expr, nullptr); - IR* predicate = new IR(IRTYPE::kPredicate, OP0(), bit_expr, nullptr); - IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), predicate, nullptr); - IR* expr = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); - IR* exor_root = new IR(IRTYPE::kExprRoot, OP0(), expr, nullptr); - IR* expr_root_list = new IR(IRTYPE::kExprRootList, OP0(), exor_root, nullptr); - - simple_expr_root_list_ = expr_root_list; - simpleIR_.push_back(simple_expr_root_list_); - - return; -} -void IRTrim::instantiate_simple_simple_select_item_list() { - IR* expr_root = deep_copy(simple_expr_root_); - IR* alise = new IR(IRTYPE::kOptAlias, OP3(TERMINAL::tAs, TERMINAL::tEmpty, TERMINAL::tEmpty), deep_copy(simple_alias_), nullptr); - IR* select_item = new IR(IRTYPE::kSelectItem, OP0(), expr_root, alise); - IR* select_item_list = new IR(IRTYPE::kSelectItemList, OP0(), select_item, nullptr); - - simple_select_item_list_ = select_item_list; - simpleIR_.push_back(simple_select_item_list_); - - return; -} -void IRTrim::instantiate_simple_window_spec() { - IR* opt_existing_window_name = new IR(IRTYPE::kOptExistingWindowName, OP0(), nullptr, nullptr); - IR* opt_partition_clause = new IR(IRTYPE::kOptPartitionClause, OP0(), nullptr, nullptr); - IR* opt_window_order_by_clause = new IR(IRTYPE::kOptWindowOrderByClause, OP0(), nullptr, nullptr); - IR* opt_window_frame_clause = new IR(IRTYPE::kOptWindowFrameClause, OP0(), nullptr, nullptr); - - IR* tmp1 = new IR(IRTYPE::kWindowSpecDetailsTmp1, OP0(), opt_window_order_by_clause, opt_window_frame_clause); - IR* tmp2 = new IR(IRTYPE::kWindowSpecDetailsTmp2, OP0(), opt_partition_clause, tmp1); - IR* window_spec_details = new IR(IRTYPE::kWindowSpecDetails, OP0(), opt_existing_window_name, tmp2); - - IR* window_spec = new IR(IRTYPE::kWindowSpec, OP3(TERMINAL::tOpLp, TERMINAL::tOpRp, TERMINAL::tEmpty), window_spec_details, nullptr); - - simple_window_spec_ = window_spec; - simpleIR_.push_back(simple_window_spec_); - - return; -} -void IRTrim::instantiate_simple_index_name() { - IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* index_name = new IR(IRTYPE::kIndexName, OP0(), ident, nullptr); - - simple_index_name_ = index_name; - simpleIR_.push_back(simple_index_name_); - - return; -} -void IRTrim::instantiate_simple_constraint_name() { - IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* constraint_name = new IR(IRTYPE::kConstraintName, OP0(), ident, nullptr); - - simple_constraint_name_ = constraint_name; - simpleIR_.push_back(simple_constraint_name_); - - return; -} -void IRTrim::instantiate_simple_key_part() { - IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), ident, nullptr); - IR* opt_ordering_direction = new IR(IRTYPE::kOptOrderingDirection, OP0(), nullptr, nullptr); - IR* key_part = new IR(IRTYPE::kKeyPart, OP0(), column_name, opt_ordering_direction); - - simple_key_part_ = key_part; - simpleIR_.push_back(simple_key_part_); - - return; -} -void IRTrim::instantiate_simple_key_part_list() { - IR* key_part = deep_copy(simple_key_part_); - IR* key_list = new IR(IRTYPE::kKeyList, OP0(), key_part, nullptr); - - simple_key_part_list_ = key_list; - simpleIR_.push_back(simple_key_part_list_); - - return; -} -void IRTrim::instantiate_simple_table_element() { - IR* int_type = new IR(IRTYPE::kIntType, OP3(TERMINAL::tInt, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - IR* opt_field_options = new IR(IRTYPE::kOptFieldOptions, OP0(), nullptr, nullptr); - IR* number_type = new IR(IRTYPE::kNumberType, OP0(), int_type, opt_field_options); - IR* data_type = new IR(IRTYPE::kDataType, OP0(), number_type, nullptr); - IR* opt_column_attribute_list = new IR(IRTYPE::kOptColumnAttributeList, OP0(), nullptr, nullptr); - IR* field_def = new IR(IRTYPE::kFieldDef, OP0(), data_type, opt_column_attribute_list); - - IR* ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), ident, nullptr); - IR* column_def = new IR(IRTYPE::kColumnDef, OP0(), column_name, field_def); - - IR* table_element = new IR(IRTYPE::kTableElement, OP0(), column_def, nullptr); - - simple_table_element_ = table_element; - simpleIR_.push_back(simple_table_element_); - - return; -} -void IRTrim::instantiate_simple_values() { - IR* expr_or_default = new IR(IRTYPE::kExprOrDefault, OP3(TERMINAL::tDefault, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - IR* values = new IR(IRTYPE::kValues, OP0(), expr_or_default, nullptr); - - simple_values_ = values; - simpleIR_.push_back(simple_values_); - - return; -} - -IR* IRTrim::get_expr_root_columnref(Column* column) { - IR* tmp1 = nullptr; - - if (column->duplicated_ == ColumnStatus::csDuplication) { - IR* table_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* table_name = new IR(IRTYPE::kTableName, OP0(), table_ident, nullptr); - - instantiator_->instantiate_ident(table_name, IdentifierType::iTable, column->parentTable_->identifierName_); - - IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); - - instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); - - tmp1 = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tOpDot, TERMINAL::tEmpty), table_name, column_name); - } - else { - IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); - - instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, column->identifierName_); - - tmp1 = new IR(IRTYPE::kColumnref, OP3(TERMINAL::tEmpty, TERMINAL::tEmpty, TERMINAL::tEmpty), column_name, nullptr); - } - - IR* tmp2 = new IR(IRTYPE::kSimpleExpr, OP0(), tmp1, nullptr); - IR* tmp3 = new IR(IRTYPE::kBitExpr, OP0(), tmp2, nullptr); - IR* tmp4 = new IR(IRTYPE::kPredicate, OP0(), tmp3, nullptr); - IR* tmp5 = new IR(IRTYPE::kBoolPri, OP0(), tmp4, nullptr); - IR* tmp6 = new IR(IRTYPE::kExpr, OP0(), tmp5, nullptr); - IR* tmp7 = new IR(IRTYPE::kExprRoot, OP0(), tmp6, nullptr); - - return tmp7; -} -void IRTrim::set_recursive_limit(IR* expr_root) { - IR* number_tmp1 = new IR(IRTYPE::kIconst, OP0(), nullptr, nullptr); - number_tmp1->long_val_ = rand() % LIMITMAX; - - IR* number_tmp2 = new IR(IRTYPE::kSimpleExpr, OP0(), number_tmp1, nullptr); - IR* number_tmp3 = new IR(IRTYPE::kBitExpr, OP0(), number_tmp2, nullptr); - IR* number_tmp4 = new IR(IRTYPE::kPredicate, OP0(), number_tmp3, nullptr); - - - IR* column_ident = new IR(IRTYPE::kIdent, OP0(), nullptr, nullptr); - IR* column_name = new IR(IRTYPE::kColumnName, OP0(), column_ident, nullptr); - - instantiator_->instantiate_ident(column_name, IdentifierType::iColumn, RESERVEDCOLUMNNAME); - - IR* tmp1 = new IR(IRTYPE::kColumnref, OP0(), column_name, nullptr); - IR* tmp2 = new IR(IRTYPE::kSimpleExpr, OP0(), tmp1, nullptr); - IR* tmp3 = new IR(IRTYPE::kBitExpr, OP0(), tmp2, nullptr); - IR* tmp4 = new IR(IRTYPE::kPredicate, OP0(), tmp3, nullptr); - IR* tmp5 = new IR(IRTYPE::kBoolPri, OP0(), tmp4, nullptr); - - IR* comp_op = new IR(IRTYPE::kCompOp, OP3(TERMINAL::tOpLessthan, TERMINAL::tEmpty, TERMINAL::tEmpty), nullptr, nullptr); - - IR* bool_pri_tmp1 = new IR(IRTYPE::kBoolPriTmp1, OP0(), comp_op, number_tmp4); - IR* bool_pri = new IR(IRTYPE::kBoolPri, OP0(), tmp5, bool_pri_tmp1); - - IR* expr_right = new IR(IRTYPE::kExpr, OP0(), bool_pri, nullptr); - IR* expr_left = NT_check(expr_root->left_, IRTYPE::kExpr); - - IR* new_expr = new IR(IRTYPE::kExpr, OP3(TERMINAL::tEmpty, TERMINAL::tAnd, TERMINAL::tEmpty), expr_left, expr_right); - - expr_root->left_ = new_expr; - - return; -} \ No newline at end of file -- Gitee From ff98673e81cb282f468bd25889e41b8524acaf57 Mon Sep 17 00:00:00 2001 From: PengJiaScu Date: Thu, 16 Nov 2023 07:59:30 +0000 Subject: [PATCH 7/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AFL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AFL/Makefile | 47 - AFL/afl-as.h | 727 ------ AFL/afl-fuzz.c | 6606 ----------------------------------------------- AFL/alloc-inl.h | 577 ----- AFL/config.h | 357 --- AFL/debug.h | 258 -- AFL/hash.h | 111 - AFL/types.h | 94 - 8 files changed, 8777 deletions(-) delete mode 100755 AFL/Makefile delete mode 100755 AFL/afl-as.h delete mode 100755 AFL/afl-fuzz.c delete mode 100755 AFL/alloc-inl.h delete mode 100755 AFL/config.h delete mode 100755 AFL/debug.h delete mode 100755 AFL/hash.h delete mode 100755 AFL/types.h diff --git a/AFL/Makefile b/AFL/Makefile deleted file mode 100755 index 64dca1d..0000000 --- a/AFL/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# american fuzzy lop - makefile -# ----------------------------- -# -# Written and maintained by Michal Zalewski -# -# Copyright 2013, 2014, 2015, 2016, 2017 Google LLC All rights reserved. -# -# 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 -# - -PROGNAME = afl -VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2) - -#PGSQL_INSTALL_PATH = /mnt/raidhhd/postgrebin_no_instru# Replace with your own path -PGSQL_LIB_PATH = /home/wx/openGauss-server/inst_build/lib -PGSQL_INCLUDE_PATH = /home/wx/openGauss-server/inst_build/include -PREFIX ?= /usr/local -BIN_PATH = $(PREFIX)/bin -HELPER_PATH = $(PREFIX)/lib/afl -DOC_PATH = $(PREFIX)/share/doc/afl -MISC_PATH = $(PREFIX)/share/afl -DEPEN_PATH = ../src/*.cpp ../parser/bison_parser.cpp ../parser/flex_lexer.cpp - -# PROGS intentionally omit afl-as, which gets installed elsewhere. - -PROGS = afl-fuzz - -CC = g++ -CFLAGS ?= -fpermissive --std=c++17 #-fsanitize=address -CFLAGS += -g -w \ - -DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \ - -DBIN_PATH=\"$(BIN_PATH)\" - -COMM_HDR = alloc-inl.h config.h debug.h types.h - -all: $(PROGS) - -afl-fuzz: afl-fuzz.c $(COMM_HDR) - $(CC) $(CFLAGS) -I$(PGSQL_INCLUDE_PATH) -L$(PGSQL_LIB_PATH) -g $@.c $(DEPEN_PATH) -o $@ $(LDFLAGS) -ldl -lpq - -clean: - rm -f afl-fuzz diff --git a/AFL/afl-as.h b/AFL/afl-as.h deleted file mode 100755 index 276b8a4..0000000 --- a/AFL/afl-as.h +++ /dev/null @@ -1,727 +0,0 @@ -/* - Copyright 2013 Google LLC All rights reserved. - - 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. -*/ - -/* - american fuzzy lop - injectable parts - ------------------------------------- - - Written and maintained by Michal Zalewski - - Forkserver design by Jann Horn - - This file houses the assembly-level instrumentation injected into fuzzed - programs. The instrumentation stores XORed pairs of data: identifiers of the - currently executing branch and the one that executed immediately before. - - TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++ - - The code is designed for 32-bit and 64-bit x86 systems. Both modes should - work everywhere except for Apple systems. Apple does relocations differently - from everybody else, so since their OSes have been 64-bit for a longer while, - I didn't go through the mental effort of porting the 32-bit code. - - In principle, similar code should be easy to inject into any well-behaved - binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural - targets for instrumentation, and should offer comparable probe density. - -*/ - -#ifndef _HAVE_AFL_AS_H -#define _HAVE_AFL_AS_H - -#include "config.h" -#include "types.h" - -/* - ------------------ - Performances notes - ------------------ - - Contributions to make this code faster are appreciated! Here are some - rough notes that may help with the task: - - - Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are - really worth optimizing; the setup / fork server stuff matters a lot less - and should be mostly just kept readable. - - - We're aiming for modern CPUs with out-of-order execution and large - pipelines; the code is mostly follows intuitive, human-readable - instruction ordering, because "textbook" manual reorderings make no - substantial difference. - - - Interestingly, instrumented execution isn't a lot faster if we store a - variable pointer to the setup, log, or return routine and then do a reg - call from within trampoline_fmt. It does speed up non-instrumented - execution quite a bit, though, since that path just becomes - push-call-ret-pop. - - - There is also not a whole lot to be gained by doing SHM attach at a - fixed address instead of retrieving __afl_area_ptr. Although it allows us - to have a shorter log routine inserted for conditional jumps and jump - labels (for a ~10% perf gain), there is a risk of bumping into other - allocations created by the program or by tools such as ASAN. - - - popf is *awfully* slow, which is why we're doing the lahf / sahf + - overflow test trick. Unfortunately, this forces us to taint eax / rax, but - this dependency on a commonly-used register still beats the alternative of - using pushf / popf. - - One possible optimization is to avoid touching flags by using a circular - buffer that stores just a sequence of current locations, with the XOR stuff - happening offline. Alas, this doesn't seem to have a huge impact: - - https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ - - - Preforking one child a bit sooner, and then waiting for the "go" command - from within the child, doesn't offer major performance gains; fork() seems - to be relatively inexpensive these days. Preforking multiple children does - help, but badly breaks the "~1 core per fuzzer" design, making it harder to - scale up. Maybe there is some middle ground. - - Perhaps of note: in the 64-bit version for all platforms except for Apple, - the instrumentation is done slightly differently than on 32-bit, with - __afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm), - rather than global (.comm). This is to avoid GOTRELPC lookups in the critical - code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to - work; simple relocations between .bss and .text won't work on most 64-bit - platforms in such a case. - - (Fun fact: on Apple systems, .lcomm can segfault the linker.) - - The side effect is that state transitions are measured in a somewhat - different way, with previous tuple being recorded separately within the scope - of every .c file. This should have no impact in any practical sense. - - Another side effect of this design is that getenv() will be called once per - every .o file when running in non-instrumented mode; and since getenv() tends - to be optimized in funny ways, we need to be very careful to save every - oddball register it may touch. - - */ - -static const u8* trampoline_fmt_32 = - - "\n" - "/* --- AFL TRAMPOLINE (32-BIT) --- */\n" - "\n" - ".align 4\n" - "\n" - "leal -16(%%esp), %%esp\n" - "movl %%edi, 0(%%esp)\n" - "movl %%edx, 4(%%esp)\n" - "movl %%ecx, 8(%%esp)\n" - "movl %%eax, 12(%%esp)\n" - "movl $0x%08x, %%ecx\n" - "call __afl_maybe_log\n" - "movl 12(%%esp), %%eax\n" - "movl 8(%%esp), %%ecx\n" - "movl 4(%%esp), %%edx\n" - "movl 0(%%esp), %%edi\n" - "leal 16(%%esp), %%esp\n" - "\n" - "/* --- END --- */\n" - "\n"; - -static const u8* trampoline_fmt_64 = - - "\n" - "/* --- AFL TRAMPOLINE (64-BIT) --- */\n" - "\n" - ".align 4\n" - "\n" - "leaq -(128+24)(%%rsp), %%rsp\n" - "movq %%rdx, 0(%%rsp)\n" - "movq %%rcx, 8(%%rsp)\n" - "movq %%rax, 16(%%rsp)\n" - "movq $0x%08x, %%rcx\n" - "call __afl_maybe_log\n" - "movq 16(%%rsp), %%rax\n" - "movq 8(%%rsp), %%rcx\n" - "movq 0(%%rsp), %%rdx\n" - "leaq (128+24)(%%rsp), %%rsp\n" - "\n" - "/* --- END --- */\n" - "\n"; - -static const u8* main_payload_32 = - - "\n" - "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n" - "\n" - ".text\n" - ".att_syntax\n" - ".code32\n" - ".align 8\n" - "\n" - - "__afl_maybe_log:\n" - "\n" - " lahf\n" - " seto %al\n" - "\n" - " /* Check if SHM region is already mapped. */\n" - "\n" - " movl __afl_area_ptr, %edx\n" - " testl %edx, %edx\n" - " je __afl_setup\n" - "\n" - "__afl_store:\n" - "\n" - " /* Calculate and store hit for the code location specified in ecx. There\n" - " is a double-XOR way of doing this without tainting another register,\n" - " and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n" - "\n" -#ifndef COVERAGE_ONLY - " movl __afl_prev_loc, %edi\n" - " xorl %ecx, %edi\n" - " shrl $1, %ecx\n" - " movl %ecx, __afl_prev_loc\n" -#else - " movl %ecx, %edi\n" -#endif /* ^!COVERAGE_ONLY */ - "\n" -#ifdef SKIP_COUNTS - " orb $1, (%edx, %edi, 1)\n" -#else - " incb (%edx, %edi, 1)\n" -#endif /* ^SKIP_COUNTS */ - "\n" - "__afl_return:\n" - "\n" - " addb $127, %al\n" - " sahf\n" - " ret\n" - "\n" - ".align 8\n" - "\n" - "__afl_setup:\n" - "\n" - " /* Do not retry setup if we had previous failures. */\n" - "\n" - " cmpb $0, __afl_setup_failure\n" - " jne __afl_return\n" - "\n" - " /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n" - " We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n" - " will notice this early in the game. */\n" - "\n" - " pushl %eax\n" - " pushl %ecx\n" - "\n" - " pushl $.AFL_SHM_ENV\n" - " call getenv\n" - " addl $4, %esp\n" - "\n" - " testl %eax, %eax\n" - " je __afl_setup_abort\n" - "\n" - " pushl %eax\n" - " call atoi\n" - " addl $4, %esp\n" - "\n" - " pushl $0 /* shmat flags */\n" - " pushl $0 /* requested addr */\n" - " pushl %eax /* SHM ID */\n" - " call shmat\n" - " addl $12, %esp\n" - "\n" - " cmpl $-1, %eax\n" - " je __afl_setup_abort\n" - "\n" - " /* Store the address of the SHM region. */\n" - "\n" - " movl %eax, __afl_area_ptr\n" - " movl %eax, %edx\n" - "\n" - " popl %ecx\n" - " popl %eax\n" - "\n" - "__afl_forkserver:\n" - "\n" - " /* Enter the fork server mode to avoid the overhead of execve() calls. */\n" - "\n" - " pushl %eax\n" - " pushl %ecx\n" - " pushl %edx\n" - "\n" - " /* Phone home and tell the parent that we're OK. (Note that signals with\n" - " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" - " closed because we were execve()d from an instrumented binary, or because\n" - " the parent doesn't want to use the fork server. */\n" - "\n" - " pushl $4 /* length */\n" - " pushl $__afl_temp /* data */\n" - " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" - " call write\n" - " addl $12, %esp\n" - "\n" - " cmpl $4, %eax\n" - " jne __afl_fork_resume\n" - "\n" - "__afl_fork_wait_loop:\n" - "\n" - " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" - "\n" - " pushl $4 /* length */\n" - " pushl $__afl_temp /* data */\n" - " pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n" - " call read\n" - " addl $12, %esp\n" - "\n" - " cmpl $4, %eax\n" - " jne __afl_die\n" - "\n" - " /* Once woken up, create a clone of our process. This is an excellent use\n" - " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" - " caches getpid() results and offers no way to update the value, breaking\n" - " abort(), raise(), and a bunch of other things :-( */\n" - "\n" - " call fork\n" - "\n" - " cmpl $0, %eax\n" - " jl __afl_die\n" - " je __afl_fork_resume\n" - "\n" - " /* In parent process: write PID to pipe, then wait for child. */\n" - "\n" - " movl %eax, __afl_fork_pid\n" - "\n" - " pushl $4 /* length */\n" - " pushl $__afl_fork_pid /* data */\n" - " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" - " call write\n" - " addl $12, %esp\n" - "\n" - " pushl $0 /* no flags */\n" - " pushl $__afl_temp /* status */\n" - " pushl __afl_fork_pid /* PID */\n" - " call waitpid\n" - " addl $12, %esp\n" - "\n" - " cmpl $0, %eax\n" - " jle __afl_die\n" - "\n" - " /* Relay wait status to pipe, then loop back. */\n" - "\n" - " pushl $4 /* length */\n" - " pushl $__afl_temp /* data */\n" - " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" - " call write\n" - " addl $12, %esp\n" - "\n" - " jmp __afl_fork_wait_loop\n" - "\n" - "__afl_fork_resume:\n" - "\n" - " /* In child process: close fds, resume execution. */\n" - "\n" - " pushl $" STRINGIFY(FORKSRV_FD) "\n" - " call close\n" - "\n" - " pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n" - " call close\n" - "\n" - " addl $8, %esp\n" - "\n" - " popl %edx\n" - " popl %ecx\n" - " popl %eax\n" - " jmp __afl_store\n" - "\n" - "__afl_die:\n" - "\n" - " xorl %eax, %eax\n" - " call _exit\n" - "\n" - "__afl_setup_abort:\n" - "\n" - " /* Record setup failure so that we don't keep calling\n" - " shmget() / shmat() over and over again. */\n" - "\n" - " incb __afl_setup_failure\n" - " popl %ecx\n" - " popl %eax\n" - " jmp __afl_return\n" - "\n" - ".AFL_VARS:\n" - "\n" - " .comm __afl_area_ptr, 4, 32\n" - " .comm __afl_setup_failure, 1, 32\n" -#ifndef COVERAGE_ONLY - " .comm __afl_prev_loc, 4, 32\n" -#endif /* !COVERAGE_ONLY */ - " .comm __afl_fork_pid, 4, 32\n" - " .comm __afl_temp, 4, 32\n" - "\n" - ".AFL_SHM_ENV:\n" - " .asciz \"" SHM_ENV_VAR "\"\n" - "\n" - "/* --- END --- */\n" - "\n"; - -/* The OpenBSD hack is due to lahf and sahf not being recognized by some - versions of binutils: http://marc.info/?l=openbsd-cvs&m=141636589924400 - - The Apple code is a bit different when calling libc functions because - they are doing relocations differently from everybody else. We also need - to work around the crash issue with .lcomm and the fact that they don't - recognize .string. */ - -#ifdef __APPLE__ -# define CALL_L64(str) "call _" str "\n" -#else -# define CALL_L64(str) "call " str "@PLT\n" -#endif /* ^__APPLE__ */ - -static const u8* main_payload_64 = - - "\n" - "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n" - "\n" - ".text\n" - ".att_syntax\n" - ".code64\n" - ".align 8\n" - "\n" - "__afl_maybe_log:\n" - "\n" -#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) - " .byte 0x9f /* lahf */\n" -#else - " lahf\n" -#endif /* ^__OpenBSD__, etc */ - " seto %al\n" - "\n" - " /* Check if SHM region is already mapped. */\n" - "\n" - " movq __afl_area_ptr(%rip), %rdx\n" - " testq %rdx, %rdx\n" - " je __afl_setup\n" - "\n" - "__afl_store:\n" - "\n" - " /* Calculate and store hit for the code location specified in rcx. */\n" - "\n" -#ifndef COVERAGE_ONLY - " xorq __afl_prev_loc(%rip), %rcx\n" - " xorq %rcx, __afl_prev_loc(%rip)\n" - " shrq $1, __afl_prev_loc(%rip)\n" -#endif /* ^!COVERAGE_ONLY */ - "\n" -#ifdef SKIP_COUNTS - " orb $1, (%rdx, %rcx, 1)\n" -#else - " incb (%rdx, %rcx, 1)\n" -#endif /* ^SKIP_COUNTS */ - "\n" - "__afl_return:\n" - "\n" - " addb $127, %al\n" -#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) - " .byte 0x9e /* sahf */\n" -#else - " sahf\n" -#endif /* ^__OpenBSD__, etc */ - " ret\n" - "\n" - ".align 8\n" - "\n" - "__afl_setup:\n" - "\n" - " /* Do not retry setup if we had previous failures. */\n" - "\n" - " cmpb $0, __afl_setup_failure(%rip)\n" - " jne __afl_return\n" - "\n" - " /* Check out if we have a global pointer on file. */\n" - "\n" -#ifndef __APPLE__ - " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" - " movq (%rdx), %rdx\n" -#else - " movq __afl_global_area_ptr(%rip), %rdx\n" -#endif /* !^__APPLE__ */ - " testq %rdx, %rdx\n" - " je __afl_setup_first\n" - "\n" - " movq %rdx, __afl_area_ptr(%rip)\n" - " jmp __afl_store\n" - "\n" - "__afl_setup_first:\n" - "\n" - " /* Save everything that is not yet saved and that may be touched by\n" - " getenv() and several other libcalls we'll be relying on. */\n" - "\n" - " leaq -352(%rsp), %rsp\n" - "\n" - " movq %rax, 0(%rsp)\n" - " movq %rcx, 8(%rsp)\n" - " movq %rdi, 16(%rsp)\n" - " movq %rsi, 32(%rsp)\n" - " movq %r8, 40(%rsp)\n" - " movq %r9, 48(%rsp)\n" - " movq %r10, 56(%rsp)\n" - " movq %r11, 64(%rsp)\n" - "\n" - " movq %xmm0, 96(%rsp)\n" - " movq %xmm1, 112(%rsp)\n" - " movq %xmm2, 128(%rsp)\n" - " movq %xmm3, 144(%rsp)\n" - " movq %xmm4, 160(%rsp)\n" - " movq %xmm5, 176(%rsp)\n" - " movq %xmm6, 192(%rsp)\n" - " movq %xmm7, 208(%rsp)\n" - " movq %xmm8, 224(%rsp)\n" - " movq %xmm9, 240(%rsp)\n" - " movq %xmm10, 256(%rsp)\n" - " movq %xmm11, 272(%rsp)\n" - " movq %xmm12, 288(%rsp)\n" - " movq %xmm13, 304(%rsp)\n" - " movq %xmm14, 320(%rsp)\n" - " movq %xmm15, 336(%rsp)\n" - "\n" - " /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n" - "\n" - " /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n" - " original stack ptr in the callee-saved r12. */\n" - "\n" - " pushq %r12\n" - " movq %rsp, %r12\n" - " subq $16, %rsp\n" - " andq $0xfffffffffffffff0, %rsp\n" - "\n" - " leaq .AFL_SHM_ENV(%rip), %rdi\n" - CALL_L64("getenv") - "\n" - " testq %rax, %rax\n" - " je __afl_setup_abort\n" - "\n" - " movq %rax, %rdi\n" - CALL_L64("atoi") - "\n" - " xorq %rdx, %rdx /* shmat flags */\n" - " xorq %rsi, %rsi /* requested addr */\n" - " movq %rax, %rdi /* SHM ID */\n" - CALL_L64("shmat") - "\n" - " cmpq $-1, %rax\n" - " je __afl_setup_abort\n" - "\n" - " /* Store the address of the SHM region. */\n" - "\n" - " movq %rax, %rdx\n" - " movq %rax, __afl_area_ptr(%rip)\n" - "\n" -#ifdef __APPLE__ - " movq %rax, __afl_global_area_ptr(%rip)\n" -#else - " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" - " movq %rax, (%rdx)\n" -#endif /* ^__APPLE__ */ - " movq %rax, %rdx\n" - "\n" - "__afl_forkserver:\n" - "\n" - " /* Enter the fork server mode to avoid the overhead of execve() calls. We\n" - " push rdx (area ptr) twice to keep stack alignment neat. */\n" - "\n" - " pushq %rdx\n" - " pushq %rdx\n" - "\n" - " /* Phone home and tell the parent that we're OK. (Note that signals with\n" - " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" - " closed because we were execve()d from an instrumented binary, or because\n" - " the parent doesn't want to use the fork server. */\n" - "\n" - " movq $4, %rdx /* length */\n" - " leaq __afl_temp(%rip), %rsi /* data */\n" - " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" - CALL_L64("write") - "\n" - " cmpq $4, %rax\n" - " jne __afl_fork_resume\n" - "\n" - "__afl_fork_wait_loop:\n" - "\n" - " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" - "\n" - " movq $4, %rdx /* length */\n" - " leaq __afl_temp(%rip), %rsi /* data */\n" - " movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n" - CALL_L64("read") - " cmpq $4, %rax\n" - " jne __afl_die\n" - "\n" - " /* Once woken up, create a clone of our process. This is an excellent use\n" - " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" - " caches getpid() results and offers no way to update the value, breaking\n" - " abort(), raise(), and a bunch of other things :-( */\n" - "\n" - CALL_L64("fork") - " cmpq $0, %rax\n" - " jl __afl_die\n" - " je __afl_fork_resume\n" - "\n" - " /* In parent process: write PID to pipe, then wait for child. */\n" - "\n" - " movl %eax, __afl_fork_pid(%rip)\n" - "\n" - " movq $4, %rdx /* length */\n" - " leaq __afl_fork_pid(%rip), %rsi /* data */\n" - " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" - CALL_L64("write") - "\n" - " movq $0, %rdx /* no flags */\n" - " leaq __afl_temp(%rip), %rsi /* status */\n" - " movq __afl_fork_pid(%rip), %rdi /* PID */\n" - CALL_L64("waitpid") - " cmpq $0, %rax\n" - " jle __afl_die\n" - "\n" - " /* Relay wait status to pipe, then loop back. */\n" - "\n" - " movq $4, %rdx /* length */\n" - " leaq __afl_temp(%rip), %rsi /* data */\n" - " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" - CALL_L64("write") - "\n" - " jmp __afl_fork_wait_loop\n" - "\n" - "__afl_fork_resume:\n" - "\n" - " /* In child process: close fds, resume execution. */\n" - "\n" - " movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n" - CALL_L64("close") - "\n" - " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n" - CALL_L64("close") - "\n" - " popq %rdx\n" - " popq %rdx\n" - "\n" - " movq %r12, %rsp\n" - " popq %r12\n" - "\n" - " movq 0(%rsp), %rax\n" - " movq 8(%rsp), %rcx\n" - " movq 16(%rsp), %rdi\n" - " movq 32(%rsp), %rsi\n" - " movq 40(%rsp), %r8\n" - " movq 48(%rsp), %r9\n" - " movq 56(%rsp), %r10\n" - " movq 64(%rsp), %r11\n" - "\n" - " movq 96(%rsp), %xmm0\n" - " movq 112(%rsp), %xmm1\n" - " movq 128(%rsp), %xmm2\n" - " movq 144(%rsp), %xmm3\n" - " movq 160(%rsp), %xmm4\n" - " movq 176(%rsp), %xmm5\n" - " movq 192(%rsp), %xmm6\n" - " movq 208(%rsp), %xmm7\n" - " movq 224(%rsp), %xmm8\n" - " movq 240(%rsp), %xmm9\n" - " movq 256(%rsp), %xmm10\n" - " movq 272(%rsp), %xmm11\n" - " movq 288(%rsp), %xmm12\n" - " movq 304(%rsp), %xmm13\n" - " movq 320(%rsp), %xmm14\n" - " movq 336(%rsp), %xmm15\n" - "\n" - " leaq 352(%rsp), %rsp\n" - "\n" - " jmp __afl_store\n" - "\n" - "__afl_die:\n" - "\n" - " xorq %rax, %rax\n" - CALL_L64("_exit") - "\n" - "__afl_setup_abort:\n" - "\n" - " /* Record setup failure so that we don't keep calling\n" - " shmget() / shmat() over and over again. */\n" - "\n" - " incb __afl_setup_failure(%rip)\n" - "\n" - " movq %r12, %rsp\n" - " popq %r12\n" - "\n" - " movq 0(%rsp), %rax\n" - " movq 8(%rsp), %rcx\n" - " movq 16(%rsp), %rdi\n" - " movq 32(%rsp), %rsi\n" - " movq 40(%rsp), %r8\n" - " movq 48(%rsp), %r9\n" - " movq 56(%rsp), %r10\n" - " movq 64(%rsp), %r11\n" - "\n" - " movq 96(%rsp), %xmm0\n" - " movq 112(%rsp), %xmm1\n" - " movq 128(%rsp), %xmm2\n" - " movq 144(%rsp), %xmm3\n" - " movq 160(%rsp), %xmm4\n" - " movq 176(%rsp), %xmm5\n" - " movq 192(%rsp), %xmm6\n" - " movq 208(%rsp), %xmm7\n" - " movq 224(%rsp), %xmm8\n" - " movq 240(%rsp), %xmm9\n" - " movq 256(%rsp), %xmm10\n" - " movq 272(%rsp), %xmm11\n" - " movq 288(%rsp), %xmm12\n" - " movq 304(%rsp), %xmm13\n" - " movq 320(%rsp), %xmm14\n" - " movq 336(%rsp), %xmm15\n" - "\n" - " leaq 352(%rsp), %rsp\n" - "\n" - " jmp __afl_return\n" - "\n" - ".AFL_VARS:\n" - "\n" - -#ifdef __APPLE__ - - " .comm __afl_area_ptr, 8\n" -#ifndef COVERAGE_ONLY - " .comm __afl_prev_loc, 8\n" -#endif /* !COVERAGE_ONLY */ - " .comm __afl_fork_pid, 4\n" - " .comm __afl_temp, 4\n" - " .comm __afl_setup_failure, 1\n" - -#else - - " .lcomm __afl_area_ptr, 8\n" -#ifndef COVERAGE_ONLY - " .lcomm __afl_prev_loc, 8\n" -#endif /* !COVERAGE_ONLY */ - " .lcomm __afl_fork_pid, 4\n" - " .lcomm __afl_temp, 4\n" - " .lcomm __afl_setup_failure, 1\n" - -#endif /* ^__APPLE__ */ - - " .comm __afl_global_area_ptr, 8, 8\n" - "\n" - ".AFL_SHM_ENV:\n" - " .asciz \"" SHM_ENV_VAR "\"\n" - "\n" - "/* --- END --- */\n" - "\n"; - -#endif /* !_HAVE_AFL_AS_H */ diff --git a/AFL/afl-fuzz.c b/AFL/afl-fuzz.c deleted file mode 100755 index c024cb2..0000000 --- a/AFL/afl-fuzz.c +++ /dev/null @@ -1,6606 +0,0 @@ -/* - Copyright 2013 Google LLC All rights reserved. - - 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. -*/ - -/* - american fuzzy lop - fuzzer code - -------------------------------- - - Written and maintained by Michal Zalewski - - Forkserver design by Jann Horn - - This is the real deal: the program takes an instrumented binary and - attempts a variety of basic fuzzing tricks, paying close attention to - how they affect the execution path. - -*/ - -#define AFL_MAIN -#define MESSAGES_TO_STDOUT - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#define _FILE_OFFSET_BITS 64 - -#include "config.h" -#include "types.h" -#include "debug.h" -#include "alloc-inl.h" -#include "hash.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../include/ast.h" -#include "../include/mutate.h" -#include "../include//instantiate.h" -#include "../include/define.h" -#include "../include/connector.h" - -using namespace std; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) -# include -#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ - -/* For systems that have sched_setaffinity; right now just Linux, but one - can hope... */ - -#ifdef __linux__ -# define HAVE_AFFINITY 1 -#endif /* __linux__ */ - -/* A toggle to export some variables when building as a library. Not very - useful for the general public. */ - -#ifdef AFL_LIB -# define EXP_ST -#else -# define EXP_ST static -#endif /* ^AFL_LIB */ - -/* Lots of globals, but mostly for the status UI and other things where it - really makes no sense to haul them around as function parameters. */ - -#define ABPATH "/home/omm/openGauss_Fuzzer_release/" -#define RLPATH_LIB "/corpus/initlib" -#define RLPATH_IRINFO "/corpus/IR_config" -#define RLPATH_OUTPUT "/" - -#define INIT_LIB ABPATH RLPATH_LIB -#define GRAMMAR_INFORMATION ABPATH RLPATH_IRINFO -#define OUTPUT_PATH ABPATH RLPATH_OUTPUT - -#define HOST "localhost" -#define USERNAME "omm" -#define PASSWORD "Aa1!@#$%^&*()" -#define PORT 5432 - -#define SERVERNAME "gaussdb" -const char* file = "/home/wx/openGauss-server/inst_build/bin/gs_ctl"; -char* const options[] = { "/home/wx/openGauss-server/inst_build/bin/gs_ctl", "start", "-D", "/home/omm/data", "-Z", "single_node", "-l", "/home/omm/log/opengauss.log", NULL }; - -static long seed_count = 0; - -char* g_current_sql = nullptr; -InputInfo* g_current_input = nullptr; - -Mutator g_mutator; -Instantiator g_instantiator; -Connector g_connector(HOST, USERNAME, PASSWORD, PORT, SERVERNAME); - -EXP_ST u8 vaild_flag = 0; -EXP_ST u64 total_vaild = 0; - -EXP_ST u8 *in_dir, /* Input directory with test cases */ - *out_file, /* File to fuzz, if any */ - *out_dir, /* Working & output directory */ - *sync_dir, /* Synchronization directory */ - *sync_id, /* Fuzzer ID */ - *use_banner, /* Display banner */ - *in_bitmap, /* Input bitmap */ - *doc_path, /* Path to documentation dir */ - *target_path, /* Path to target binary */ - *orig_cmdline; /* Original command line */ - -EXP_ST u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */ -static u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */ - -EXP_ST u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */ - -static u32 stats_update_freq = 1; /* Stats update frequency (execs) */ - -EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */ - force_deterministic, /* Force deterministic stages? */ - use_splicing, /* Recombine input files? */ - dumb_mode, /* Run in non-instrumented mode? */ - score_changed, /* Scoring for favorites changed? */ - kill_signal, /* Signal that killed the child */ - resuming_fuzz, /* Resuming an older fuzzing job? */ - timeout_given, /* Specific timeout given? */ - not_on_tty, /* stdout is not a tty */ - term_too_small, /* terminal dimensions too small */ - uses_asan, /* Target uses ASAN? */ - no_forkserver, /* Disable forkserver? */ - crash_mode, /* Crash mode! Yeah! */ - in_place_resume, /* Attempt in-place resume? */ - auto_changed, /* Auto-generated tokens changed? */ - no_cpu_meter_red, /* Feng shui on the status screen */ - no_arith, /* Skip most arithmetic ops */ - shuffle_queue, /* Shuffle input queue? */ - bitmap_changed = 1, /* Time to update bitmap? */ - qemu_mode, /* Running in QEMU mode? */ - skip_requested, /* Skip request, via SIGUSR1 */ - run_over10m, /* Run time over 10 minutes? */ - persistent_mode, /* Running in persistent mode? */ - deferred_mode, /* Deferred forkserver mode? */ - fast_cal; /* Try to calibrate faster? */ - -static s32 out_fd, /* Persistent fd for out_file */ - dev_urandom_fd = -1, /* Persistent fd for /dev/urandom */ - dev_null_fd = -1, /* Persistent fd for /dev/null */ - fsrv_ctl_fd, /* Fork server control pipe (write) */ - fsrv_st_fd; /* Fork server status pipe (read) */ - -static s32 forksrv_pid, /* PID of the fork server */ - child_pid = -1, /* PID of the fuzzed program */ - out_dir_fd = -1; /* FD of the lock file */ - -EXP_ST u8* trace_bits; /* SHM with instrumentation bitmap */ - -EXP_ST u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ - virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ - virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */ - -static u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ - -static s32 shm_id; /* ID of the SHM region */ - -static volatile u8 stop_soon, /* Ctrl-C pressed? */ - clear_screen = 1, /* Window resized? */ - child_timed_out; /* Traced process timed out? */ - -EXP_ST u32 queued_paths, /* Total number of queued testcases */ - queued_variable, /* Testcases with variable behavior */ - queued_at_start, /* Total number of initial inputs */ - queued_discovered, /* Items discovered during this run */ - queued_imported, /* Items imported via -S */ - queued_favored, /* Paths deemed favorable */ - queued_with_cov, /* Paths with new coverage bytes */ - pending_not_fuzzed, /* Queued but not done yet */ - pending_favored, /* Pending favored paths */ - cur_skipped_paths, /* Abandoned inputs in cur cycle */ - cur_depth, /* Current path depth */ - max_depth, /* Max path depth */ - useless_at_start, /* Number of useless starting paths */ - var_byte_count, /* Bitmap bytes with var behavior */ - current_entry, /* Current queue entry ID */ - havoc_div = 1; /* Cycle count divisor for havoc */ - -EXP_ST u64 total_crashes, /* Total number of crashes */ - unique_crashes, /* Crashes with unique signatures */ - total_tmouts, /* Total number of timeouts */ - unique_tmouts, /* Timeouts with unique signatures */ - unique_hangs, /* Hangs with unique signatures */ - total_execs, /* Total execve() calls */ - cur_execs, - slowest_exec_ms, /* Slowest testcase non hang in ms */ - start_time, /* Unix start time (ms) */ - last_save_time, - last_path_time, /* Time for most recent path (ms) */ - last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time, /* Time for most recent hang (ms) */ - last_crash_execs, /* Exec counter at last crash */ - queue_cycle, /* Queue round counter */ - cycles_wo_finds, /* Cycles without any new paths */ - trim_execs, /* Execs done to trim input files */ - bytes_trim_in, /* Bytes coming into the trimmer */ - bytes_trim_out, /* Bytes coming outa the trimmer */ - blocks_eff_total, /* Blocks subject to effector maps */ - blocks_eff_select; /* Blocks selected as fuzzable */ - -static u32 subseq_tmouts; /* Number of timeouts in a row */ - -static u8 *stage_name = "init", /* Name of the current fuzz stage */ - *stage_short, /* Short stage name */ - *syncing_party; /* Currently syncing with... */ - -static s32 stage_cur, stage_max; /* Stage progression */ -static s32 splicing_with = -1; /* Splicing with which test case? */ - -static u32 master_id, master_max; /* Master instance job splitting */ - -static u32 syncing_case; /* Syncing with case #... */ - -static s32 stage_cur_byte, /* Byte offset of current stage op */ - stage_cur_val; /* Value used for stage op */ - -static u8 stage_val_type; /* Value type (STAGE_VAL_*) */ - -static u64 stage_finds[32], /* Patterns found per fuzz stage */ - stage_cycles[32]; /* Execs per fuzz stage */ - -static u32 rand_cnt; /* Random number counter */ - -static u64 total_cal_us, /* Total calibration time (us) */ - total_cal_cycles = 1; /* Total calibration cycles */ - -static u64 total_bitmap_size, /* Total bit count for all bitmaps */ - total_bitmap_entries; /* Number of bitmaps counted */ - -static s32 cpu_core_count; /* CPU core count */ - -#ifdef HAVE_AFFINITY - -static s32 cpu_aff = -1; /* Selected CPU core */ - -#endif /* HAVE_AFFINITY */ - -static FILE* plot_file; /* Gnuplot output file */ - -struct queue_entry { - - u8* fname; /* File name for the test case */ - u32 len; /* Input length */ - - u8 cal_failed, /* Calibration failed? */ - trim_done, /* Trimmed? */ - was_fuzzed, /* Had any fuzzing done yet? */ - passed_det, /* Deterministic stages passed? */ - has_new_cov, /* Triggers new coverage? */ - var_behavior, /* Variable behavior? */ - favored, /* Currently favored? */ - fs_redundant; /* Marked as redundant in the fs? */ - - u32 bitmap_size, /* Number of bits set in bitmap */ - exec_cksum; /* Checksum of the execution trace */ - - u64 exec_us, /* Execution time (us) */ - handicap, /* Number of queue cycles behind */ - depth; /* Path depth */ - - u8* trace_mini; /* Trace bytes, if kept */ - u32 tc_ref; /* Trace bytes ref count */ - - struct queue_entry *next, /* Next element, if any */ - *next_100; /* 100 elements ahead */ - -}; - - -static struct queue_entry *queue, /* Fuzzing queue (linked list) */ - *queue_cur, /* Current offset within the queue */ - *queue_top, /* Top of the list */ - *q_prev100; /* Previous 100 marker */ - -static struct queue_entry* - top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */ - -struct extra_data { - u8* data; /* Dictionary token data */ - u32 len; /* Dictionary token length */ - u32 hit_cnt; /* Use count in the corpus */ -}; - -static struct extra_data* extras; /* Extra tokens to fuzz with */ -static u32 extras_cnt; /* Total number of tokens read */ - -static struct extra_data* a_extras; /* Automatically selected extras */ -static u32 a_extras_cnt; /* Total number of tokens available */ - -static u8* (*post_handler)(u8* buf, u32* len); - -/* Interesting values, as per config.h */ - -static s8 interesting_8[] = { INTERESTING_8 }; -static s16 interesting_16[] = { INTERESTING_8, INTERESTING_16 }; -static s32 interesting_32[] = { INTERESTING_8, INTERESTING_16, INTERESTING_32 }; - -/* Fuzzing stages */ - -enum { - /* 00 */ STAGE_FLIP1, - /* 01 */ STAGE_FLIP2, - /* 02 */ STAGE_FLIP4, - /* 03 */ STAGE_FLIP8, - /* 04 */ STAGE_FLIP16, - /* 05 */ STAGE_FLIP32, - /* 06 */ STAGE_ARITH8, - /* 07 */ STAGE_ARITH16, - /* 08 */ STAGE_ARITH32, - /* 09 */ STAGE_INTEREST8, - /* 10 */ STAGE_INTEREST16, - /* 11 */ STAGE_INTEREST32, - /* 12 */ STAGE_EXTRAS_UO, - /* 13 */ STAGE_EXTRAS_UI, - /* 14 */ STAGE_EXTRAS_AO, - /* 15 */ STAGE_HAVOC, - /* 16 */ STAGE_SPLICE -}; - -/* Stage value types */ - -enum { - /* 00 */ STAGE_VAL_NONE, - /* 01 */ STAGE_VAL_LE, - /* 02 */ STAGE_VAL_BE -}; - -/* Execution status fault codes */ - -enum { - /* 00 */ FAULT_NONE, - /* 01 */ FAULT_TMOUT, - /* 02 */ FAULT_CRASH, - /* 03 */ FAULT_ERROR, - /* 04 */ FAULT_NOINST, - /* 05 */ FAULT_NOBITS -}; - - -/* Get unix time in milliseconds */ -static u64 get_cur_time(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); - -} - -/* Get unix time in microseconds */ - -static u64 get_cur_time_us(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000000ULL) + tv.tv_usec; - -} - - -/* Generate a random number (from 0 to limit - 1). This may - have slight bias. */ - -static inline u32 UR(u32 limit) { - - if (unlikely(!rand_cnt--)) { - - u32 seed[2]; - - ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom"); - - srandom(seed[0]); - rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG); - - } - - return random() % limit; - -} - - -/* Shuffle an array of pointers. Might be slightly biased. */ - -static void shuffle_ptrs(void** ptrs, u32 cnt) { - - u32 i; - - for (i = 0; i < cnt - 2; i++) { - - u32 j = i + UR(cnt - i); - void *s = ptrs[i]; - ptrs[i] = ptrs[j]; - ptrs[j] = s; - - } - -} - - -#ifdef HAVE_AFFINITY - -/* Build a list of processes bound to specific cores. Returns -1 if nothing - can be found. Assumes an upper bound of 4k CPUs. */ - -static void bind_to_free_cpu(void) { - - DIR* d; - struct dirent* de; - cpu_set_t c; - - u8 cpu_used[4096] = { 0 }; - u32 i; - - if (cpu_core_count < 2) return; - - if (getenv("AFL_NO_AFFINITY")) { - - WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set)."); - return; - - } - - d = opendir("/proc"); - - if (!d) { - - WARNF("Unable to access /proc - can't scan for free CPU cores."); - return; - - } - - ACTF("Checking CPU core loadout..."); - - /* Introduce some jitter, in case multiple AFL tasks are doing the same - thing at the same time... */ - - usleep(R(1000) * 250); - - /* Scan all /proc//status entries, checking for Cpus_allowed_list. - Flag all processes bound to a specific CPU using cpu_used[]. This will - fail for some exotic binding setups, but is likely good enough in almost - all real-world use cases. */ - - while ((de = readdir(d))) { - - u8* fn; - FILE* f; - u8 tmp[MAX_LINE]; - u8 has_vmsize = 0; - - if (!isdigit(de->d_name[0])) continue; - - fn = alloc_printf("/proc/%s/status", de->d_name); - - if (!(f = fopen(fn, "r"))) { - ck_free(fn); - continue; - } - - while (fgets(tmp, MAX_LINE, f)) { - - u32 hval; - - /* Processes without VmSize are probably kernel tasks. */ - - if (!strncmp(tmp, "VmSize:\t", 8)) has_vmsize = 1; - - if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && - !strchr((char *)tmp, int('-')) && !strchr((char *)tmp, int(',')) && - sscanf(tmp + 19, "%u", &hval) == 1 && hval < sizeof(cpu_used) && - has_vmsize) { - - cpu_used[hval] = 1; - break; - - } - - } - - ck_free(fn); - fclose(f); - - } - - closedir(d); - - for (i = 0; i < cpu_core_count; i++) if (!cpu_used[i]) break; - - if (i == cpu_core_count) { - - SAYF("\n" cLRD "[-] " cRST - "Uh-oh, looks like all %u CPU cores on your system are allocated to\n" - " other instances of afl-fuzz (or similar CPU-locked tasks). Starting\n" - " another fuzzer on this machine is probably a bad plan, but if you are\n" - " absolutely sure, you can set AFL_NO_AFFINITY and try again.\n", - cpu_core_count); - - FATAL("No more free CPU cores"); - - } - - OKF("Found a free CPU core, binding to #%u.", i); - - cpu_aff = i; - - CPU_ZERO(&c); - CPU_SET(i, &c); - - if (sched_setaffinity(0, sizeof(c), &c)) - PFATAL("sched_setaffinity failed"); - -} - -#endif /* HAVE_AFFINITY */ - -#ifndef IGNORE_FINDS - -/* Helper function to compare buffers; returns first and last differing offset. We - use this to find reasonable locations for splicing two files. */ - -static void locate_diffs(u8* ptr1, u8* ptr2, u32 len, s32* first, s32* last) { - - s32 f_loc = -1; - s32 l_loc = -1; - u32 pos; - - for (pos = 0; pos < len; pos++) { - - if (*(ptr1++) != *(ptr2++)) { - - if (f_loc == -1) f_loc = pos; - l_loc = pos; - - } - - } - - *first = f_loc; - *last = l_loc; - - return; - -} - -#endif /* !IGNORE_FINDS */ - - -/* Describe integer. Uses 12 cyclic static buffers for return values. The value - returned should be five characters or less for all the integers we reasonably - expect to see. */ - -static u8* DI(u64 val) { - - static u8 tmp[12][16]; - static u8 cur; - - cur = (cur + 1) % 12; - -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) do { \ - if (val < (_divisor) * (_limit_mult)) { \ - sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \ - return tmp[cur]; \ - } \ - } while (0) - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1000, 99.95, "%0.01fk", double); - - /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); - - /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); - - /* 100G - 999G */ - CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); - - /* 100T+ */ - strcpy(tmp[cur], "infty"); - return tmp[cur]; - -} - - -/* Describe float. Similar to the above, except with a single - static buffer. */ - -static u8* DF(double val) { - - static u8 tmp[16]; - - if (val < 99.995) { - sprintf(tmp, "%0.02f", val); - return tmp; - } - - if (val < 999.95) { - sprintf(tmp, "%0.01f", val); - return tmp; - } - - return DI((u64)val); - -} - - -/* Describe integer as memory size. */ - -static u8* DMS(u64 val) { - - static u8 tmp[12][16]; - static u8 cur; - - cur = (cur + 1) % 12; - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1024, 99.95, "%0.01f kB", double); - - /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); - - /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); - - /* 100G - 999G */ - CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); - -#undef CHK_FORMAT - - /* 100T+ */ - strcpy(tmp[cur], "infty"); - return tmp[cur]; - -} - - -/* Describe time delta. Returns one static buffer, 34 chars of less. */ - -static u8* DTD(u64 cur_ms, u64 event_ms) { - - static u8 tmp[64]; - u64 delta; - s32 t_d, t_h, t_m, t_s; - - if (!event_ms) return "none seen yet"; - - delta = cur_ms - event_ms; - - t_d = delta / 1000 / 60 / 60 / 24; - t_h = (delta / 1000 / 60 / 60) % 24; - t_m = (delta / 1000 / 60) % 60; - t_s = (delta / 1000) % 60; - - sprintf(tmp, "%s days, %u hrs, %u min, %u sec", DI(t_d), t_h, t_m, t_s); - return tmp; - -} - - -/* Mark deterministic checks as done for a particular queue entry. We use the - .state file to avoid repeating deterministic fuzzing when resuming aborted - scans. */ - -static void mark_as_det_done(struct queue_entry* q) { - - u8* fn = strrchr((const char*)q->fname, '/'); - s32 fd; - - fn = alloc_printf("%s/queue/.state/deterministic_done/%s", out_dir, fn + 1); - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - close(fd); - - ck_free(fn); - - q->passed_det = 1; - -} - - -/* Mark as variable. Create symlinks if possible to make it easier to examine - the files. */ - -static void mark_as_variable(struct queue_entry* q) { - - u8 *fn = strrchr((char *)q->fname, '/') + 1, *ldest; - - ldest = alloc_printf("../../%s", fn); - fn = alloc_printf("%s/queue/.state/variable_behavior/%s", out_dir, fn); - - if (symlink(ldest, fn)) { - - s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - close(fd); - - } - - ck_free(ldest); - ck_free(fn); - - q->var_behavior = 1; - -} - - -/* Mark / unmark as redundant (edge-only). This is not used for restoring state, - but may be useful for post-processing datasets. */ - -static void mark_as_redundant(struct queue_entry* q, u8 state) { - - u8* fn; - s32 fd; - - if (state == q->fs_redundant) return; - - q->fs_redundant = state; - - fn = strrchr((const char*)q->fname, '/'); - fn = alloc_printf("%s/queue/.state/redundant_edges/%s", out_dir, fn + 1); - - if (state) { - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - close(fd); - - } else { - - if (unlink(fn)) PFATAL("Unable to remove '%s'", fn); - - } - - ck_free(fn); - -} - - -/* Append new test case to the queue. */ - -static void add_to_queue(u8* fname, u32 len, u8 passed_det) { - - struct queue_entry* q = ck_alloc(sizeof(struct queue_entry)); - - q->fname = fname; - q->len = len; - q->depth = cur_depth + 1; - q->passed_det = passed_det; - - if (q->depth > max_depth) max_depth = q->depth; - - if (queue_top) { - - queue_top->next = q; - queue_top = q; - - } else q_prev100 = queue = queue_top = q; - - queued_paths++; - pending_not_fuzzed++; - - cycles_wo_finds = 0; - - if (!(queued_paths % 100)) { - - q_prev100->next_100 = q; - q_prev100 = q; - - } - - last_path_time = get_cur_time(); - -} - - -/* Destroy the entire queue. */ - -EXP_ST void destroy_queue(void) { - - struct queue_entry *q = queue, *n; - - while (q) { - - n = q->next; - ck_free(q->fname); - ck_free(q->trace_mini); - ck_free(q); - q = n; - - } - -} - - -/* Write bitmap to file. The bitmap is useful mostly for the secret - -B option, to focus a separate fuzzing session on a particular - interesting input without rediscovering all the others. */ - -EXP_ST void write_bitmap(void) { - - u8* fname; - s32 fd; - - if (!bitmap_changed) return; - bitmap_changed = 0; - - fname = alloc_printf("%s/fuzz_bitmap", out_dir); - fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to open '%s'", fname); - - ck_write(fd, virgin_bits, MAP_SIZE, fname); - - close(fd); - ck_free(fname); - -} - - -/* Read bitmap from file. This is for the -B option again. */ - -EXP_ST void read_bitmap(u8* fname) { - - s32 fd = open(fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", fname); - - ck_read(fd, virgin_bits, MAP_SIZE, fname); - - close(fd); - -} - - -/* Check if the current execution path brings anything new to the table. - Update virgin bits to reflect the finds. Returns 1 if the only change is - the hit-count for a particular tuple; 2 if there are new tuples seen. - Updates the map, so subsequent calls will always return 0. - - This function is called after every exec() on a fairly large buffer, so - it needs to be fast. We do this in 32-bit and 64-bit flavors. */ - -static inline u8 has_new_bits(u8* virgin_map) { - -#ifdef __x86_64__ - - u64* current = (u64*)trace_bits; - u64* virgin = (u64*)virgin_map; - - u32 i = (MAP_SIZE >> 3); - -#else - - u32* current = (u32*)trace_bits; - u32* virgin = (u32*)virgin_map; - - u32 i = (MAP_SIZE >> 2); - -#endif /* ^__x86_64__ */ - - u8 ret = 0; - - while (i--) { - - /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap - that have not been already cleared from the virgin map - since this will - almost always be the case. */ - - if (unlikely(*current) && unlikely(*current & *virgin)) { - - if (likely(ret < 2)) { - - u8* cur = (u8*)current; - u8* vir = (u8*)virgin; - - /* Looks like we have not found any new bytes yet; see if any non-zero - bytes in current[] are pristine in virgin[]. */ - -#ifdef __x86_64__ - - if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || - (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || - (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || - (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) ret = 2; - else ret = 1; - -#else - - if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || - (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) ret = 2; - else ret = 1; - -#endif /* ^__x86_64__ */ - - } - - *virgin &= ~*current; - - } - - current++; - virgin++; - - } - - if (ret && virgin_map == virgin_bits) bitmap_changed = 1; - - return ret; - -} - - -/* Count the number of bits set in the provided bitmap. Used for the status - screen several times every second, does not have to be fast. */ - -static u32 count_bits(u8* mem) { - - u32* ptr = (u32*)mem; - u32 i = (MAP_SIZE >> 2); - u32 ret = 0; - - while (i--) { - - u32 v = *(ptr++); - - /* This gets called on the inverse, virgin bitmap; optimize for sparse - data. */ - - if (v == 0xffffffff) { - ret += 32; - continue; - } - - v -= ((v >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; - - } - - return ret; - -} - - -#define FF(_b) (0xff << ((_b) << 3)) - -/* Count the number of bytes set in the bitmap. Called fairly sporadically, - mostly to update the status screen or calibrate and examine confirmed - new paths. */ - -static u32 count_bytes(u8* mem) { - - u32* ptr = (u32*)mem; - u32 i = (MAP_SIZE >> 2); - u32 ret = 0; - - while (i--) { - - u32 v = *(ptr++); - - if (!v) continue; - if (v & FF(0)) ret++; - if (v & FF(1)) ret++; - if (v & FF(2)) ret++; - if (v & FF(3)) ret++; - - } - - return ret; - -} - - -/* Count the number of non-255 bytes set in the bitmap. Used strictly for the - status screen, several calls per second or so. */ - -static u32 count_non_255_bytes(u8* mem) { - - u32* ptr = (u32*)mem; - u32 i = (MAP_SIZE >> 2); - u32 ret = 0; - - while (i--) { - - u32 v = *(ptr++); - - /* This is called on the virgin bitmap, so optimize for the most likely - case. */ - - if (v == 0xffffffff) continue; - if ((v & FF(0)) != FF(0)) ret++; - if ((v & FF(1)) != FF(1)) ret++; - if ((v & FF(2)) != FF(2)) ret++; - if ((v & FF(3)) != FF(3)) ret++; - - } - - return ret; - -} - - -/* Destructively simplify trace by eliminating hit count information - and replacing it with 0x80 or 0x01 depending on whether the tuple - is hit or not. Called on every new crash or timeout, should be - reasonably fast. */ - -static u8 simplify_lookup[256] = {0}; - -#ifdef __x86_64__ - -static void simplify_trace(u64* mem) { - - u32 i = MAP_SIZE >> 3; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u8* mem8 = (u8*)mem; - - mem8[0] = simplify_lookup[mem8[0]]; - mem8[1] = simplify_lookup[mem8[1]]; - mem8[2] = simplify_lookup[mem8[2]]; - mem8[3] = simplify_lookup[mem8[3]]; - mem8[4] = simplify_lookup[mem8[4]]; - mem8[5] = simplify_lookup[mem8[5]]; - mem8[6] = simplify_lookup[mem8[6]]; - mem8[7] = simplify_lookup[mem8[7]]; - - } else *mem = 0x0101010101010101ULL; - - mem++; - - } - -} - -#else - -static void simplify_trace(u32* mem) { - - u32 i = MAP_SIZE >> 2; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u8* mem8 = (u8*)mem; - - mem8[0] = simplify_lookup[mem8[0]]; - mem8[1] = simplify_lookup[mem8[1]]; - mem8[2] = simplify_lookup[mem8[2]]; - mem8[3] = simplify_lookup[mem8[3]]; - - } else *mem = 0x01010101; - - mem++; - } - -} - -#endif /* ^__x86_64__ */ - - -/* Destructively classify execution counts in a trace. This is used as a - preprocessing step for any newly acquired traces. Called on every exec, - must be fast. */ - -static u8 count_class_lookup8[256] = {0}; - -static u16 count_class_lookup16[65536]; - -void memset_fucking_array(){ - simplify_lookup[0] = 1; - memset(simplify_lookup+1, 128, 255); - - count_class_lookup8[0] = 0; - count_class_lookup8[1] = 1; - count_class_lookup8[2] = 2; - count_class_lookup8[3] = 4; - memset(count_class_lookup8 + 4, 8, 7 - 4 + 1); - memset(count_class_lookup8 + 8, 16, 15 - 8 + 1); - memset(count_class_lookup8 + 16, 32, 32 - 16); - memset(count_class_lookup8 + 32, 64, 128 - 32); - memset(count_class_lookup8 + 128, 128, 128); -} - -EXP_ST void init_count_class16(void) { - - u32 b1, b2; - - for (b1 = 0; b1 < 256; b1++) - for (b2 = 0; b2 < 256; b2++) - count_class_lookup16[(b1 << 8) + b2] = - (count_class_lookup8[b1] << 8) | - count_class_lookup8[b2]; - -} - - -#ifdef __x86_64__ - -static inline void classify_counts(u64* mem) { - - u32 i = MAP_SIZE >> 3; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u16* mem16 = (u16*)mem; - - mem16[0] = count_class_lookup16[mem16[0]]; - mem16[1] = count_class_lookup16[mem16[1]]; - mem16[2] = count_class_lookup16[mem16[2]]; - mem16[3] = count_class_lookup16[mem16[3]]; - - } - - mem++; - - } - -} - -#else - -static inline void classify_counts(u32* mem) { - - u32 i = MAP_SIZE >> 2; - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { - - u16* mem16 = (u16*)mem; - - mem16[0] = count_class_lookup16[mem16[0]]; - mem16[1] = count_class_lookup16[mem16[1]]; - - } - - mem++; - - } - -} - -#endif /* ^__x86_64__ */ - - -/* Get rid of shared memory (atexit handler). */ - -static void remove_shm(void) { - - shmctl(shm_id, IPC_RMID, NULL); - -} - - -/* Compact trace bytes into a smaller bitmap. We effectively just drop the - count information here. This is called only sporadically, for some - new paths. */ - -static void minimize_bits(u8* dst, u8* src) { - - u32 i = 0; - - while (i < MAP_SIZE) { - - if (*(src++)) dst[i >> 3] |= 1 << (i & 7); - i++; - - } - -} - - -/* When we bump into a new path, we call this to see if the path appears - more "favorable" than any of the existing ones. The purpose of the - "favorables" is to have a minimal set of paths that trigger all the bits - seen in the bitmap so far, and focus on fuzzing them at the expense of - the rest. - - The first step of the process is to maintain a list of top_rated[] entries - for every byte in the bitmap. We win that slot if there is no previous - contender, or if the contender has a more favorable speed x size factor. */ - -static void update_bitmap_score(struct queue_entry* q) { - - u32 i; - u64 fav_factor = q->exec_us * q->len; - - /* For every byte set in trace_bits[], see if there is a previous winner, - and how it compares to us. */ - - for (i = 0; i < MAP_SIZE; i++) - - if (trace_bits[i]) { - - if (top_rated[i]) { - - /* Faster-executing or smaller test cases are favored. */ - - if (fav_factor > top_rated[i]->exec_us * top_rated[i]->len) continue; - - /* Looks like we're going to win. Decrease ref count for the - previous winner, discard its trace_bits[] if necessary. */ - - if (!--top_rated[i]->tc_ref) { - ck_free(top_rated[i]->trace_mini); - top_rated[i]->trace_mini = 0; - } - - } - - /* Insert ourselves as the new winner. */ - - top_rated[i] = q; - q->tc_ref++; - - if (!q->trace_mini) { - q->trace_mini = ck_alloc(MAP_SIZE >> 3); - minimize_bits(q->trace_mini, trace_bits); - } - - score_changed = 1; - - } - -} - - -/* The second part of the mechanism discussed above is a routine that - goes over top_rated[] entries, and then sequentially grabs winners for - previously-unseen bytes (temp_v) and marks them as favored, at least - until the next run. The favored entries are given more air time during - all fuzzing steps. */ - -static void cull_queue(void) { - - struct queue_entry* q; - static u8 temp_v[MAP_SIZE >> 3]; - u32 i; - - if (dumb_mode || !score_changed) return; - - score_changed = 0; - - memset(temp_v, 255, MAP_SIZE >> 3); - - queued_favored = 0; - pending_favored = 0; - - q = queue; - - while (q) { - q->favored = 0; - q = q->next; - } - - /* Let's see if anything in the bitmap isn't captured in temp_v. - If yes, and if it has a top_rated[] contender, let's use it. */ - - for (i = 0; i < MAP_SIZE; i++) - if (top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { - - u32 j = MAP_SIZE >> 3; - - /* Remove all bits belonging to the current entry from temp_v. */ - - while (j--) - if (top_rated[i]->trace_mini[j]) - temp_v[j] &= ~top_rated[i]->trace_mini[j]; - - top_rated[i]->favored = 1; - queued_favored++; - - if (!top_rated[i]->was_fuzzed) pending_favored++; - - } - - q = queue; - - while (q) { - mark_as_redundant(q, !q->favored); - q = q->next; - } - -} - - -/* Configure shared memory and virgin_bits. This is called at startup. */ - -EXP_ST void setup_shm(void) { - - u8* shm_str; - - if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); - - memset(virgin_tmout, 255, MAP_SIZE); - memset(virgin_crash, 255, MAP_SIZE); - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - /* If somebody is asking us to fuzz instrumented binaries in dumb mode, - we don't want them to detect instrumentation, since we won't be sending - fork server commands. This should be replaced with better auto-detection - later on, perhaps? */ - - if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); - ck_free(shm_str); - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); - -} - - -/* Load postprocessor, if available. */ - -static void setup_post(void) { - - void* dh; - u8* fn = getenv("AFL_POST_LIBRARY"); - u32 tlen = 6; - - if (!fn) return; - - ACTF("Loading postprocessor from '%s'...", fn); - - dh = dlopen(fn, RTLD_NOW); - if (!dh) FATAL("%s", dlerror()); - - post_handler = dlsym(dh, "afl_postprocess"); - if (!post_handler) FATAL("Symbol 'afl_postprocess' not found."); - - /* Do a quick test. It's better to segfault now than later =) */ - - post_handler("hello", &tlen); - - OKF("Postprocessor installed successfully."); - -} - - -/* Read all testcases from the input directory, then queue them for testing. - Called at startup. */ - -static void read_testcases(void) { - - struct dirent **nl; - s32 nl_cnt; - u32 i; - u8* fn; - - /* Auto-detect non-in-place resumption attempts. */ - - fn = alloc_printf("%s/queue", in_dir); - if (!access(fn, F_OK)) in_dir = fn; else ck_free(fn); - - ACTF("Scanning '%s'...", in_dir); - - /* We use scandir() + alphasort() rather than readdir() because otherwise, - the ordering of test cases would vary somewhat randomly and would be - difficult to control. */ - - nl_cnt = scandir(in_dir, &nl, NULL, alphasort); - - if (nl_cnt < 0) { - - if (errno == ENOENT || errno == ENOTDIR) - - SAYF("\n" cLRD "[-] " cRST - "The input directory does not seem to be valid - try again. The fuzzer needs\n" - " one or more test case to start with - ideally, a small file under 1 kB\n" - " or so. The cases must be stored as regular files directly in the input\n" - " directory.\n"); - - PFATAL("Unable to open '%s'", in_dir); - - } - - if (shuffle_queue && nl_cnt > 1) { - - ACTF("Shuffling queue..."); - shuffle_ptrs((void**)nl, nl_cnt); - - } - - for (i = 0; i < nl_cnt; i++) { - - struct stat st; - - u8* fn = alloc_printf("%s/%s", in_dir, nl[i]->d_name); - u8* dfn = alloc_printf("%s/.state/deterministic_done/%s", in_dir, nl[i]->d_name); - - u8 passed_det = 0; - - free(nl[i]); /* not tracked */ - - if (lstat(fn, &st) || access(fn, R_OK)) - PFATAL("Unable to access '%s'", fn); - - /* This also takes care of . and .. */ - - if (!S_ISREG(st.st_mode) || !st.st_size || strstr((char *)fn, "/README.txt")) { - - ck_free(fn); - ck_free(dfn); - continue; - - } - - if (st.st_size > MAX_FILE) - FATAL("Test case '%s' is too big (%s, limit is %s)", fn, - DMS(st.st_size), DMS(MAX_FILE)); - - /* Check for metadata that indicates that deterministic fuzzing - is complete for this entry. We don't want to repeat deterministic - fuzzing when resuming aborted scans, because it would be pointless - and probably very time-consuming. */ - - if (!access(dfn, F_OK)) passed_det = 1; - ck_free(dfn); - - add_to_queue(fn, st.st_size, passed_det); - - } - - free(nl); /* not tracked */ - - if (!queued_paths) { - - SAYF("\n" cLRD "[-] " cRST - "Looks like there are no valid test cases in the input directory! The fuzzer\n" - " needs one or more test case to start with - ideally, a small file under\n" - " 1 kB or so. The cases must be stored as regular files directly in the\n" - " input directory.\n"); - - FATAL("No usable test cases in '%s'", in_dir); - - } - - last_path_time = 0; - queued_at_start = queued_paths; - -} - - -/* Helper function for load_extras. */ - -static int compare_extras_len(const void* p1, const void* p2) { - struct extra_data *e1 = (struct extra_data*)p1, - *e2 = (struct extra_data*)p2; - - return e1->len - e2->len; -} - -static int compare_extras_use_d(const void* p1, const void* p2) { - struct extra_data *e1 = (struct extra_data*)p1, - *e2 = (struct extra_data*)p2; - - return e2->hit_cnt - e1->hit_cnt; -} - - -/* Read extras from a file, sort by size. */ - -static void load_extras_file(u8* fname, u32* min_len, u32* max_len, - u32 dict_level) { - - FILE* f; - u8 buf[MAX_LINE]; - u8 *lptr; - u32 cur_line = 0; - - f = fopen(fname, "r"); - - if (!f) PFATAL("Unable to open '%s'", fname); - - while ((lptr = fgets(buf, MAX_LINE, f))) { - - u8 *rptr, *wptr; - u32 klen = 0; - - cur_line++; - - /* Trim on left and right. */ - - while (isspace(*lptr)) lptr++; - - rptr = lptr + strlen(lptr) - 1; - while (rptr >= lptr && isspace(*rptr)) rptr--; - rptr++; - *rptr = 0; - - /* Skip empty lines and comments. */ - - if (!*lptr || *lptr == '#') continue; - - /* All other lines must end with '"', which we can consume. */ - - rptr--; - - if (rptr < lptr || *rptr != '"') - FATAL("Malformed name=\"value\" pair in line %u.", cur_line); - - *rptr = 0; - - /* Skip alphanumerics and dashes (label). */ - - while (isalnum(*lptr) || *lptr == '_') lptr++; - - /* If @number follows, parse that. */ - - if (*lptr == '@') { - - lptr++; - if (atoi(lptr) > dict_level) continue; - while (isdigit(*lptr)) lptr++; - - } - - /* Skip whitespace and = signs. */ - - while (isspace(*lptr) || *lptr == '=') lptr++; - - /* Consume opening '"'. */ - - if (*lptr != '"') - FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); - - lptr++; - - if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); - - /* Okay, let's allocate memory and copy data between "...", handling - \xNN escaping, \\, and \". */ - - extras = ck_realloc_block(extras, (extras_cnt + 1) * - sizeof(struct extra_data)); - - wptr = extras[extras_cnt].data = ck_alloc(rptr - lptr); - - while (*lptr) { - - char* hexdigits = "0123456789abcdef"; - - switch (*lptr) { - - case 1 ... 31: - case 128 ... 255: - FATAL("Non-printable characters in line %u.", cur_line); - - case '\\': - - lptr++; - - if (*lptr == '\\' || *lptr == '"') { - *(wptr++) = *(lptr++); - klen++; - break; - } - - if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) - FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); - - *(wptr++) = - ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) | - (strchr(hexdigits, tolower(lptr[2])) - hexdigits); - - lptr += 3; - klen++; - - break; - - default: - - *(wptr++) = *(lptr++); - klen++; - - } - - } - - extras[extras_cnt].len = klen; - - if (extras[extras_cnt].len > MAX_DICT_FILE) - FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, - DMS(klen), DMS(MAX_DICT_FILE)); - - if (*min_len > klen) *min_len = klen; - if (*max_len < klen) *max_len = klen; - - extras_cnt++; - - } - - fclose(f); - -} - - -/* Read extras from the extras directory and sort them by size. */ - -static void load_extras(u8* dir) { - - DIR* d; - struct dirent* de; - u32 min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0; - u8* x; - - /* If the name ends with @, extract level and continue. */ - - if ((x = strchr((char *)dir, '@'))) { - - *x = 0; - dict_level = atoi(x + 1); - - } - - ACTF("Loading extra dictionary from '%s' (level %u)...", dir, dict_level); - - d = opendir(dir); - - if (!d) { - - if (errno == ENOTDIR) { - load_extras_file(dir, &min_len, &max_len, dict_level); - goto check_and_sort; - } - - PFATAL("Unable to open '%s'", dir); - - } - - if (x) FATAL("Dictionary levels not supported for directories."); - - while ((de = readdir(d))) { - - struct stat st; - u8* fn = alloc_printf("%s/%s", dir, de->d_name); - s32 fd; - - if (lstat(fn, &st) || access(fn, R_OK)) - PFATAL("Unable to access '%s'", fn); - - /* This also takes care of . and .. */ - if (!S_ISREG(st.st_mode) || !st.st_size) { - - ck_free(fn); - continue; - - } - - if (st.st_size > MAX_DICT_FILE) - FATAL("Extra '%s' is too big (%s, limit is %s)", fn, - DMS(st.st_size), DMS(MAX_DICT_FILE)); - - if (min_len > st.st_size) min_len = st.st_size; - if (max_len < st.st_size) max_len = st.st_size; - - extras = ck_realloc_block(extras, (extras_cnt + 1) * - sizeof(struct extra_data)); - - extras[extras_cnt].data = ck_alloc(st.st_size); - extras[extras_cnt].len = st.st_size; - - fd = open(fn, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", fn); - - ck_read(fd, extras[extras_cnt].data, st.st_size, fn); - - close(fd); - ck_free(fn); - - extras_cnt++; - - } - - closedir(d); - -check_and_sort: - - if (!extras_cnt) FATAL("No usable files in '%s'", dir); - - qsort(extras, extras_cnt, sizeof(struct extra_data), compare_extras_len); - - OKF("Loaded %u extra tokens, size range %s to %s.", extras_cnt, - DMS(min_len), DMS(max_len)); - - if (max_len > 32) - WARNF("Some tokens are relatively large (%s) - consider trimming.", - DMS(max_len)); - - if (extras_cnt > MAX_DET_EXTRAS) - WARNF("More than %u tokens - will use them probabilistically.", - MAX_DET_EXTRAS); - -} - - - - -/* Helper function for maybe_add_auto() */ - -static inline u8 memcmp_nocase(u8* m1, u8* m2, u32 len) { - - while (len--) if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1; - return 0; - -} - - -/* Maybe add automatic extra. */ - -static void maybe_add_auto(u8* mem, u32 len) { - - u32 i; - - /* Allow users to specify that they don't want auto dictionaries. */ - - if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return; - - /* Skip runs of identical bytes. */ - - for (i = 1; i < len; i++) - if (mem[0] ^ mem[i]) break; - - if (i == len) return; - - /* Reject builtin interesting values. */ - - if (len == 2) { - - i = sizeof(interesting_16) >> 1; - - while (i--) - if (*((u16*)mem) == interesting_16[i] || - *((u16*)mem) == SWAP16(interesting_16[i])) return; - - } - - if (len == 4) { - - i = sizeof(interesting_32) >> 2; - - while (i--) - if (*((u32*)mem) == interesting_32[i] || - *((u32*)mem) == SWAP32(interesting_32[i])) return; - - } - - /* Reject anything that matches existing extras. Do a case-insensitive - match. We optimize by exploiting the fact that extras[] are sorted - by size. */ - - for (i = 0; i < extras_cnt; i++) - if (extras[i].len >= len) break; - - for (; i < extras_cnt && extras[i].len == len; i++) - if (!memcmp_nocase(extras[i].data, mem, len)) return; - - /* Last but not least, check a_extras[] for matches. There are no - guarantees of a particular sort order. */ - - auto_changed = 1; - - for (i = 0; i < a_extras_cnt; i++) { - - if (a_extras[i].len == len && !memcmp_nocase(a_extras[i].data, mem, len)) { - - a_extras[i].hit_cnt++; - goto sort_a_extras; - - } - - } - - /* At this point, looks like we're dealing with a new entry. So, let's - append it if we have room. Otherwise, let's randomly evict some other - entry from the bottom half of the list. */ - - if (a_extras_cnt < MAX_AUTO_EXTRAS) { - - a_extras = ck_realloc_block(a_extras, (a_extras_cnt + 1) * - sizeof(struct extra_data)); - - a_extras[a_extras_cnt].data = ck_memdup(mem, len); - a_extras[a_extras_cnt].len = len; - a_extras_cnt++; - - } else { - - i = MAX_AUTO_EXTRAS / 2 + - UR((MAX_AUTO_EXTRAS + 1) / 2); - - ck_free(a_extras[i].data); - - a_extras[i].data = ck_memdup(mem, len); - a_extras[i].len = len; - a_extras[i].hit_cnt = 0; - - } - -sort_a_extras: - - /* First, sort all auto extras by use count, descending order. */ - - qsort(a_extras, a_extras_cnt, sizeof(struct extra_data), - compare_extras_use_d); - - /* Then, sort the top USE_AUTO_EXTRAS entries by size. */ - - qsort(a_extras, MIN(USE_AUTO_EXTRAS, a_extras_cnt), - sizeof(struct extra_data), compare_extras_len); - -} - - -/* Save automatically generated extras. */ - -static void save_auto(void) { - - u32 i; - - if (!auto_changed) return; - auto_changed = 0; - - for (i = 0; i < MIN(USE_AUTO_EXTRAS, a_extras_cnt); i++) { - - u8* fn = alloc_printf("%s/queue/.state/auto_extras/auto_%06u", out_dir, i); - s32 fd; - - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_write(fd, a_extras[i].data, a_extras[i].len, fn); - - close(fd); - ck_free(fn); - - } - -} - - -/* Load automatically generated extras. */ - -static void load_auto(void) { - - u32 i; - - for (i = 0; i < USE_AUTO_EXTRAS; i++) { - - u8 tmp[MAX_AUTO_EXTRA + 1]; - u8* fn = alloc_printf("%s/.state/auto_extras/auto_%06u", in_dir, i); - s32 fd, len; - - fd = open(fn, O_RDONLY, 0600); - - if (fd < 0) { - - if (errno != ENOENT) PFATAL("Unable to open '%s'", fn); - ck_free(fn); - break; - - } - - /* We read one byte more to cheaply detect tokens that are too - long (and skip them). */ - - len = read(fd, tmp, MAX_AUTO_EXTRA + 1); - - if (len < 0) PFATAL("Unable to read from '%s'", fn); - - if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) - maybe_add_auto(tmp, len); - - close(fd); - ck_free(fn); - - } - - if (i) OKF("Loaded %u auto-discovered dictionary tokens.", i); - else OKF("No auto-generated dictionary tokens to reuse."); - -} - - -/* Destroy extras. */ - -static void destroy_extras(void) { - - u32 i; - - for (i = 0; i < extras_cnt; i++) - ck_free(extras[i].data); - - ck_free(extras); - - for (i = 0; i < a_extras_cnt; i++) - ck_free(a_extras[i].data); - - ck_free(a_extras); - -} - - -/* Spin up fork server (instrumented mode only). The idea is explained here: - - http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html - - In essence, the instrumentation allows us to skip execve(), and just keep - cloning a stopped child. So, we just execute once, and then send commands - through a pipe. The other part of this logic is in afl-as.h. */ - -EXP_ST void init_forkserver(char** argv) { - - static struct itimerval it; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; - ACTF("Spinning up the fork server..."); - - if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); - - forksrv_pid = fork(); - - if (forksrv_pid < 0) PFATAL("fork() failed"); - - if (!forksrv_pid) { - - struct rlimit r; - - /* Umpf. On OpenBSD, the default fd limit for root users is set to - soft 128. Let's try to fix that... */ - - if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) { - - r.rlim_cur = FORKSRV_FD + 2; - setrlimit(RLIMIT_NOFILE, &r); /* Ignore errors */ - - } - - if (mem_limit) { - - r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 50; - -#ifdef RLIMIT_AS - - setrlimit(RLIMIT_AS, &r); /* Ignore errors */ - -#else - - /* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but - according to reliable sources, RLIMIT_DATA covers anonymous - maps - so we should be getting good protection against OOM bugs. */ - - setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ - -#endif /* ^RLIMIT_AS */ - - - } - - /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered - before the dump is complete. */ - - r.rlim_max = r.rlim_cur = 0; - - setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ - - /* Isolate the process and configure standard descriptors. If out_file is - specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ - - setsid(); - - dup2(dev_null_fd, 1); - dup2(dev_null_fd, 2); - - if (out_file) { - - dup2(dev_null_fd, 0); - - } else { - - dup2(out_fd, 0); - close(out_fd); - - } - - /* Set up control and status pipes, close the unneeded original fds. */ - - if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); - if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed"); - - close(ctl_pipe[0]); - close(ctl_pipe[1]); - close(st_pipe[0]); - close(st_pipe[1]); - - close(out_dir_fd); - close(dev_null_fd); - close(dev_urandom_fd); - close(fileno(plot_file)); - - /* This should improve performance a bit, since it stops the linker from - doing extra work post-fork(). */ - - if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); - - /* Set sane defaults for ASAN if nothing else specified. */ - - setenv("ASAN_OPTIONS", "abort_on_error=1:" - "detect_leaks=0:" - "symbolize=0:" - "allocator_may_return_null=1", 0); - - /* MSAN is tricky, because it doesn't support abort_on_error=1 at this - point. So, we do this in a very hacky way. */ - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "abort_on_error=1:" - "allocator_may_return_null=1:" - "msan_track_origins=0", 0); - - /* char * tmp_target_path = "/usr/local/mysql/bin/mysqld"; - char * tmp_argv[] = {"/usr/local/mysql/bin/mysqld", - "--basedir=/usr/local/mysql", - "--datadir=/usr/local/mysql/data", - "--plugin-dir=/usr/local/mysql/lib/plugin", - "--user=mysql", - "--log-error=lrs-dwu01.err", - "--pid-file=lrs-dwu01.pid", - "--socket=/tmp/mysql.sock", - NULL}; - execv(tmp_target_path, tmp_argv); //改参数把,别改这里了,我再去看看那个启动参数 -*/ - /* Use a distinctive bitmap signature to tell the parent about execv() - falling through. */ - - *(u32*)trace_bits = EXEC_FAIL_SIG; - exit(0); - - } - - /* Close the unneeded endpoints. */ - - close(ctl_pipe[0]); - close(st_pipe[1]); - - fsrv_ctl_fd = ctl_pipe[1]; - fsrv_st_fd = st_pipe[0]; - - - /* Wait for the fork server to come up, but don't wait too long. */ - - it.it_value.tv_sec = ((exec_tmout * FORK_WAIT_MULT) / 1000); - it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; - - setitimer(ITIMER_REAL, &it, NULL); - - rlen = read(fsrv_st_fd, &status, 4); - child_pid = status; - assert(child_pid != -1); - - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - - setitimer(ITIMER_REAL, &it, NULL); - - /* If we have a four-byte "hello" message from the server, we're all set. - Otherwise, try to figure out what went wrong. */ - - if (rlen == 4) { - OKF("All right - fork server is up."); - return; - } - - if (child_timed_out) - FATAL("Timeout while initializing fork server (adjusting -t may help)"); - - if (waitpid(forksrv_pid, &status, 0) <= 0) - PFATAL("waitpid() failed"); - - if (WIFSIGNALED(status)) { - - if (mem_limit && mem_limit < 500 && uses_asan) { - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the target binary crashed suddenly, before receiving any input\n" - " from the fuzzer! Since it seems to be built with ASAN and you have a\n" - " restrictive memory limit configured, this is expected; please read\n" - " %s/notes_for_asan.txt for help.\n", doc_path); - - } else if (!mem_limit) { - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the target binary crashed suddenly, before receiving any input\n" - " from the fuzzer! There are several probable explanations:\n\n" - - " - The binary is just buggy and explodes entirely on its own. If so, you\n" - " need to fix the underlying problem or find a better replacement.\n\n" - -#ifdef __APPLE__ - - " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" - " break afl-fuzz performance optimizations when running platform-specific\n" - " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" - -#endif /* __APPLE__ */ - - " - Less likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n"); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the target binary crashed suddenly, before receiving any input\n" - " from the fuzzer! There are several probable explanations:\n\n" - - " - The current memory limit (%s) is too restrictive, causing the\n" - " target to hit an OOM condition in the dynamic linker. Try bumping up\n" - " the limit with the -m setting in the command line. A simple way confirm\n" - " this diagnosis would be:\n\n" - -#ifdef RLIMIT_AS - " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#else - " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#endif /* ^RLIMIT_AS */ - - " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" - " estimate the required amount of virtual memory for the binary.\n\n" - - " - The binary is just buggy and explodes entirely on its own. If so, you\n" - " need to fix the underlying problem or find a better replacement.\n\n" - -#ifdef __APPLE__ - - " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" - " break afl-fuzz performance optimizations when running platform-specific\n" - " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" - -#endif /* __APPLE__ */ - - " - Less likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n", - DMS(mem_limit << 20), mem_limit - 1); - - } - - FATAL("Fork server crashed with signal %d", WTERMSIG(status)); - - } - - if (*(u32*)trace_bits == EXEC_FAIL_SIG) - FATAL("Unable to execute target application ('%s')", argv[0]); - - if (mem_limit && mem_limit < 500 && uses_asan) { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, looks like the target binary terminated before we could complete a\n" - " handshake with the injected code. Since it seems to be built with ASAN and\n" - " you have a restrictive memory limit configured, this is expected; please\n" - " read %s/notes_for_asan.txt for help.\n", doc_path); - - } else if (!mem_limit) { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, looks like the target binary terminated before we could complete a\n" - " handshake with the injected code. Perhaps there is a horrible bug in the\n" - " fuzzer. Poke for troubleshooting tips.\n"); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, looks like the target binary terminated before we could complete a\n" - " handshake with the injected code. There are %s probable explanations:\n\n" - - "%s" - " - The current memory limit (%s) is too restrictive, causing an OOM\n" - " fault in the dynamic linker. This can be fixed with the -m option. A\n" - " simple way to confirm the diagnosis may be:\n\n" - -#ifdef RLIMIT_AS - " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#else - " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" -#endif /* ^RLIMIT_AS */ - - " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" - " estimate the required amount of virtual memory for the binary.\n\n" - - " - Less likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n", - getenv(DEFER_ENV_VAR) ? "three" : "two", - getenv(DEFER_ENV_VAR) ? - " - You are using deferred forkserver, but __AFL_INIT() is never\n" - " reached before the program terminates.\n\n" : "", - DMS(mem_limit << 20), mem_limit - 1); - - } - - FATAL("Fork server handshake failed"); - -} - -/* Execute target application, monitoring for timeouts. Return status - information. The called program will update trace_bits[]. */ - -int counter; -static u8 run_target(char** argv, u32 timeout) { - - static struct itimerval it; - static u32 prev_timed_out = 0; - static u64 exec_ms = 0; - int status = 0; - u32 tb4; - - child_timed_out = 0; - - /* After this memset, trace_bits[] are effectively volatile, so we - must prevent any earlier operations from venturing into that - territory. */ - - memset(trace_bits, 0, MAP_SIZE); - MEM_BARRIER(); - -//********************************** - - vaild_flag = 0; - - SQLSTATUS result = g_connector.execute(g_current_sql); - - if (result == SQLSTATUS::ssConnectFailed) { - while (1) { - sleep(0.1); - - g_connector.start_db(file, options); - result = g_connector.execute(g_current_sql); - - if ((result != SQLSTATUS::ssConnectFailed) || stop_soon) { - break; - } - } - } - - if(result == SQLSTATUS::ssServerCrash){ - status = FAULT_CRASH; - }else{ - if(result == SQLSTATUS::ssNormal){ - vaild_flag = 1; - total_vaild++; - } - - status = FAULT_NONE; - } - - total_execs++; - cur_execs++; - -//********************************** - - MEM_BARRIER(); - - tb4 = *(u32*)trace_bits; - -#ifdef __x86_64__ - classify_counts((u64*)trace_bits); -#else - classify_counts((u32*)trace_bits); -#endif /* ^__x86_64__ */ - - return status; -} - - -/* Write modified data to file for testing. If out_file is set, the old file - is unlinked and a new one is created. Otherwise, out_fd is rewound and - truncated. */ - -static void write_to_testcase(void* mem, u32 len) { - - g_current_sql = (char *)mem; - return ; - -} - - -/* The same, but with an adjustable gap. Used for trimming. */ - -static void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) { - - s32 fd = out_fd; - u32 tail_len = len - skip_at - skip_len; - - if (out_file) { - - unlink(out_file); /* Ignore errors. */ - - fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", out_file); - - } else lseek(fd, 0, SEEK_SET); - - if (skip_at) ck_write(fd, mem, skip_at, out_file); - - if (tail_len) ck_write(fd, mem + skip_at + skip_len, tail_len, out_file); - - if (!out_file) { - - if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed"); - lseek(fd, 0, SEEK_SET); - - } else close(fd); - -} - - -static void show_stats(void); - -/* Calibrate a new test case. This is done when processing the input directory - to warn about flaky or otherwise problematic test cases early on; and when - new paths are discovered to detect variable behavior and so on. */ - -static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem, - u32 handicap, u8 from_queue) { - - static u8 first_trace[MAP_SIZE]; - - u8 fault = 0, new_bits = 0, var_detected = 0, - first_run = (q->exec_cksum == 0); - - u64 start_us, stop_us; - - s32 old_sc = stage_cur, old_sm = stage_max; - u32 use_tmout = exec_tmout; - u8* old_sn = stage_name; - - /* Be a bit more generous about timeouts when resuming sessions, or when - trying to calibrate already-added finds. This helps avoid trouble due - to intermittent latency. */ - - if (!from_queue || resuming_fuzz) - use_tmout = MAX(exec_tmout + CAL_TMOUT_ADD, - exec_tmout * CAL_TMOUT_PERC / 100); - - q->cal_failed++; - - stage_name = "calibration"; - stage_max = fast_cal ? 3 : CAL_CYCLES; - - /* Make sure the forkserver is up before we do anything, and let's not - count its spin-up time toward binary calibration. */ - - if (dumb_mode != 1 && !no_forkserver && !forksrv_pid){ - /* - int idx = 0; - cout << "Init fork server arguments: " << endl; - while(auto s = argv[idx]){ - cout << argv[idx++] << endl; - } - cin >> idx; - */ - //init_forkserver(argv); - } - - - if (q->exec_cksum) memcpy(first_trace, trace_bits, MAP_SIZE); - - start_us = get_cur_time_us(); - - for (stage_cur = 0; stage_cur < 1; stage_cur++) { - - u32 cksum; - - if (!first_run && !(stage_cur % stats_update_freq)) show_stats(); - - write_to_testcase(use_mem, q->len); - - fault = run_target(argv, use_tmout); - - /* stop_soon is set by the handler for Ctrl+C. When it's pressed, - we want to bail out quickly. */ - - if (stop_soon || fault != crash_mode) goto abort_calibration; - - if (!dumb_mode && !stage_cur && !count_bytes(trace_bits)) { - fault = FAULT_NOINST; - goto abort_calibration; - } - - cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - if (q->exec_cksum != cksum) { - - u8 hnb = has_new_bits(virgin_bits); - if (hnb > new_bits) new_bits = hnb; - - if (q->exec_cksum) { - - u32 i; - - for (i = 0; i < MAP_SIZE; i++) { - - if (!var_bytes[i] && first_trace[i] != trace_bits[i]) { - - var_bytes[i] = 1; - virgin_bits[i] = 0; - stage_max = CAL_CYCLES_LONG; - - } - - } - - var_detected = 1; - - } else { - - q->exec_cksum = cksum; - memcpy(first_trace, trace_bits, MAP_SIZE); - - } - - } - - } - - stop_us = get_cur_time_us(); - - total_cal_us += stop_us - start_us; - total_cal_cycles += stage_max; - - /* OK, let's collect some stats about the performance of this test case. - This is used for fuzzing air time calculations in calculate_score(). */ - - q->exec_us = (stop_us - start_us) / stage_max; - q->bitmap_size = count_bytes(trace_bits); - q->handicap = handicap; - q->cal_failed = 0; - - total_bitmap_size += q->bitmap_size; - total_bitmap_entries++; - - update_bitmap_score(q); - - /* If this case didn't result in new output from the instrumentation, tell - parent. This is a non-critical problem, but something to warn the user - about. */ - - if (!dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS; - -abort_calibration: - - if (new_bits == 2 && !q->has_new_cov) { - q->has_new_cov = 1; - queued_with_cov++; - } - - /* Mark variable paths. */ - - if (var_detected) { - - var_byte_count = count_bytes(var_bytes); - - if (!q->var_behavior) { - mark_as_variable(q); - queued_variable++; - } - - } - - stage_name = old_sn; - stage_cur = old_sc; - stage_max = old_sm; - - if (!first_run) show_stats(); - - return fault; - -} - - -/* Examine map coverage. Called once, for first test case. */ - -static void check_map_coverage(void) { - - u32 i; - - if (count_bytes(trace_bits) < 100) return; - - for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; i++) - if (trace_bits[i]) return; - - WARNF("Recompile binary with newer version of afl to improve coverage!"); - -} - - -/* Perform dry run of all test cases to confirm that the app is working as - expected. This is done only for the initial inputs, and only once. */ - -static void perform_dry_run(char** argv) { - - struct queue_entry* q = queue; - u32 cal_failures = 0; - u8* skip_crashes = getenv("AFL_SKIP_CRASHES"); - - while (q) { - - u8* use_mem; - u8 res; - s32 fd; - - u8* fn = strrchr((char *)q->fname, '/') + 1; - - ACTF("Attempting dry run with '%s'...", fn); - - fd = open(q->fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", q->fname); - - use_mem = (u8*)malloc(q->len + 1); - - if (read(fd, use_mem, q->len) != q->len) - FATAL("Short read from '%s'", q->fname); - - close(fd); - -//********************************* - - use_mem[q->len] = '\0'; - - IR* root = g_mutator.IR_parser(use_mem); - free(use_mem); - - if (root == nullptr) { - q = q->next; - continue; - } - - string ir_str = root->to_string(); - - char* tmp_str = ir_str.c_str(); - int siz = ir_str.size(); - - q->len = siz; - - res = calibrate_case(argv, q, tmp_str, 0, 1); - - if (stop_soon) return; - - //********************************* - - if (res == crash_mode || res == FAULT_NOBITS) - SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, - q->len, q->bitmap_size, q->exec_us); - - switch (res) { - - case FAULT_NONE: - - if (q == queue) check_map_coverage(); - - if (crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); - - break; - - case FAULT_TMOUT: - - if (timeout_given) { - - /* The -t nn+ syntax in the command line sets timeout_given to '2' and - instructs afl-fuzz to tolerate but skip queue entries that time - out. */ - - if (timeout_given > 1) { - WARNF("Test case results in a timeout (skipping)"); - q->cal_failed = CAL_CHANCES; - cal_failures++; - break; - } - - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial test cases.\n" - " Usually, the right thing to do is to relax the -t option - or to delete it\n" - " altogether and allow the fuzzer to auto-calibrate. That said, if you know\n" - " what you are doing and want to simply skip the unruly test cases, append\n" - " '+' at the end of the value passed to -t ('-t %u+').\n", exec_tmout, - exec_tmout); - - FATAL("Test case '%s' results in a timeout", fn); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial test cases.\n" - " This is bad news; raising the limit with the -t option is possible, but\n" - " will probably make the fuzzing process extremely slow.\n\n" - - " If this test case is just a fluke, the other option is to just avoid it\n" - " altogether, and find one that is less of a CPU hog.\n", exec_tmout); - - FATAL("Test case '%s' results in a timeout", fn); - - } - - case FAULT_CRASH: - - if (crash_mode) break; - - if (skip_crashes) { - WARNF("Test case results in a crash (skipping)"); - q->cal_failed = CAL_CHANCES; - cal_failures++; - break; - } - - if (mem_limit) { - - SAYF("\n" cLRD "[-] " cRST - "Oops, the program crashed with one of the test cases provided. There are\n" - " several possible explanations:\n\n" - - " - The test case causes known crashes under normal working conditions. If\n" - " so, please remove it. The fuzzer should be seeded with interesting\n" - " inputs - but not ones that cause an outright crash.\n\n" - - " - The current memory limit (%s) is too low for this program, causing\n" - " it to die due to OOM when parsing valid files. To fix this, try\n" - " bumping it up with the -m setting in the command line. If in doubt,\n" - " try something along the lines of:\n\n" - -#ifdef RLIMIT_AS - " ( ulimit -Sv $[%llu << 10]; /path/to/binary [...] for troubleshooting tips.\n", - DMS(mem_limit << 20), mem_limit - 1, doc_path); - - } else { - - SAYF("\n" cLRD "[-] " cRST - "Oops, the program crashed with one of the test cases provided. There are\n" - " several possible explanations:\n\n" - - " - The test case causes known crashes under normal working conditions. If\n" - " so, please remove it. The fuzzer should be seeded with interesting\n" - " inputs - but not ones that cause an outright crash.\n\n" - -#ifdef __APPLE__ - - " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" - " break afl-fuzz performance optimizations when running platform-specific\n" - " binaries. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" - -#endif /* __APPLE__ */ - - " - Least likely, there is a horrible bug in the fuzzer. If other options\n" - " fail, poke for troubleshooting tips.\n"); - - } - - FATAL("Test case '%s' results in a crash", fn); - - case FAULT_ERROR: - - FATAL("Unable to execute target application ('%s')", argv[0]); - - case FAULT_NOINST: - - FATAL("No instrumentation detected"); - - case FAULT_NOBITS: - - useless_at_start++; - - if (!in_bitmap && !shuffle_queue) - WARNF("No new instrumentation output, test case may be useless."); - - break; - - } - - if (q->var_behavior) WARNF("Instrumentation output varies across runs."); - - deep_delete(root); - - q = q->next; - - } - - if (cal_failures) { - - if (cal_failures == queued_paths) - FATAL("All test cases time out%s, giving up!", - skip_crashes ? " or crash" : ""); - - WARNF("Skipped %u test cases (%0.02f%%) due to timeouts%s.", cal_failures, - ((double)cal_failures) * 100 / queued_paths, - skip_crashes ? " or crashes" : ""); - - if (cal_failures * 5 > queued_paths) - WARNF(cLRD "High percentage of rejected test cases, check settings!"); - - } - - OKF("All test cases processed."); - -} - - -/* Helper function: link() if possible, copy otherwise. */ - -static void link_or_copy(u8* old_path, u8* new_path) { - - s32 i = link(old_path, new_path); - s32 sfd, dfd; - u8* tmp; - - if (!i) return; - - sfd = open(old_path, O_RDONLY); - if (sfd < 0) PFATAL("Unable to open '%s'", old_path); - - dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (dfd < 0) PFATAL("Unable to create '%s'", new_path); - - tmp = ck_alloc(64 * 1024); - - while ((i = read(sfd, tmp, 64 * 1024)) > 0) - ck_write(dfd, tmp, i, new_path); - - if (i < 0) PFATAL("read() failed"); - - ck_free(tmp); - close(sfd); - close(dfd); - -} - - -static void nuke_resume_dir(void); - -/* Create hard links for input test cases in the output directory, choosing - good names and pivoting accordingly. */ - -static void pivot_inputs(void) { - - struct queue_entry* q = queue; - u32 id = 0; - - ACTF("Creating hard links for all input files..."); - - while (q) { - - u8 *nfn, *rsl = strrchr((const char*)q->fname, '/'); - u32 orig_id; - - if (!rsl) rsl = q->fname; else rsl++; - - /* If the original file name conforms to the syntax and the recorded - ID matches the one we'd assign, just use the original file name. - This is valuable for resuming fuzzing runs. */ - -#ifndef SIMPLE_FILES -# define CASE_PREFIX "id:" -#else -# define CASE_PREFIX "id_" -#endif /* ^!SIMPLE_FILES */ - - if (!strncmp(rsl, CASE_PREFIX, 3) && - sscanf(rsl + 3, "%06u", &orig_id) == 1 && orig_id == id) { - - u8* src_str; - u32 src_id; - - resuming_fuzz = 1; - nfn = alloc_printf("%s/queue/%s", out_dir, rsl); - - /* Since we're at it, let's also try to find parent and figure out the - appropriate depth for this entry. */ - - src_str = strchr((char *)(rsl + 3), ':'); - - if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { - - struct queue_entry* s = queue; - while (src_id-- && s) s = s->next; - if (s) q->depth = s->depth + 1; - - if (max_depth < q->depth) max_depth = q->depth; - - } - - } else { - - /* No dice - invent a new name, capturing the original one as a - substring. */ - -#ifndef SIMPLE_FILES - - u8* use_name = strstr((const char*)rsl, ",orig:"); - - if (use_name) use_name += 6; else use_name = rsl; - nfn = alloc_printf("%s/queue/id:%06u,orig:%s", out_dir, id, use_name); - -#else - - nfn = alloc_printf("%s/queue/id_%06u", out_dir, id); - -#endif /* ^!SIMPLE_FILES */ - - } - - /* Pivot to the new queue entry. */ - - link_or_copy(q->fname, nfn); - ck_free(q->fname); - q->fname = nfn; - - /* Make sure that the passed_det value carries over, too. */ - - if (q->passed_det) mark_as_det_done(q); - - q = q->next; - id++; - - } - - if (in_place_resume) nuke_resume_dir(); - -} - - -#ifndef SIMPLE_FILES - -/* Construct a file name for a new test case, capturing the operation - that led to its discovery. Uses a static buffer. */ - -static u8* describe_op(u8 hnb) { - - static u8 ret[256]; - - if (syncing_party) { - - sprintf(ret, "sync:%s,src:%06u", syncing_party, syncing_case); - - } else { - - sprintf(ret, "src:%06u", current_entry); - - if (splicing_with >= 0) - sprintf(ret + strlen(ret), "+%06u", splicing_with); - - sprintf(ret + strlen(ret), ",op:%s", stage_short); - - if (stage_cur_byte >= 0) { - - sprintf(ret + strlen(ret), ",pos:%u", stage_cur_byte); - - if (stage_val_type != STAGE_VAL_NONE) - sprintf(ret + strlen(ret), ",val:%s%+d", - (stage_val_type == STAGE_VAL_BE) ? "be:" : "", - stage_cur_val); - - } else sprintf(ret + strlen(ret), ",rep:%u", stage_cur_val); - - } - - if (hnb == 2) strcat(ret, ",+cov"); - - return ret; - -} - -#endif /* !SIMPLE_FILES */ - - -/* Write a message accompanying the crash directory :-) */ - -static void write_crash_readme(void) { - - u8* fn = alloc_printf("%s/crashes/README.txt", out_dir); - s32 fd; - FILE* f; - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - ck_free(fn); - - /* Do not die on errors here - that would be impolite. */ - - if (fd < 0) return; - - f = fdopen(fd, "w"); - - if (!f) { - close(fd); - return; - } - - fprintf(f, "Command line used to find this crash:\n\n" - - "%s\n\n" - - "If you can't reproduce a bug outside of afl-fuzz, be sure to set the same\n" - "memory limit. The limit used for this fuzzing session was %s.\n\n" - - "Need a tool to minimize test cases before investigating the crashes or sending\n" - "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n" - - "Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop\n" - "me a mail at once the issues are fixed - I'd love to\n" - "add your finds to the gallery at:\n\n" - - " http://lcamtuf.coredump.cx/afl/\n\n" - - "Thanks :-)\n", - - orig_cmdline, DMS(mem_limit << 20)); /* ignore errors */ - - fclose(f); - -} - - -/* Check if the result of an execve() during routine fuzzing is interesting, - save or queue the input test case for further analysis if so. Returns 1 if - entry is saved, 0 otherwise. */ - -static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) { - - u8 *fn = ""; - u8 hnb; - s32 fd; - u8 keeping = 0, res; - - if (fault == crash_mode) { - - /* Keep only if there are new bits in the map, add to queue for - future fuzzing, etc. */ - - if (!(hnb = has_new_bits(virgin_bits))) { - if (crash_mode) total_crashes++; - return 0; - } - - keeping = hnb; - - if(!vaild_flag) { - goto error_check; - } - -#ifndef SIMPLE_FILES - - fn = alloc_printf("%s/queue/id:%06u,%s", out_dir, queued_paths, - describe_op(hnb)); - -#else - - fn = alloc_printf("%s/queue/id_%06u", out_dir, queued_paths); - -#endif /* ^!SIMPLE_FILES */ - - add_to_queue(fn, len, 0); - - if (hnb == 2) { - queue_top->has_new_cov = 1; - queued_with_cov++; - } - - queue_top->exec_cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - /* Try to calibrate inline; this also calls update_bitmap_score() when - successful. */ - - res = calibrate_case(argv, queue_top, mem, queue_cycle - 1, 0); - - if (res == FAULT_ERROR) - FATAL("Unable to execute target application"); - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_write(fd, mem, len, fn); - close(fd); - } - -error_check: - - switch (fault) { - - case FAULT_TMOUT: - - /* Timeouts are not very interesting, but we're still obliged to keep - a handful of samples. We use the presence of new bits in the - hang-specific bitmap as a signal of uniqueness. In "dumb" mode, we - just keep everything. */ - - total_tmouts++; - - if (unique_hangs >= KEEP_UNIQUE_HANG) return keeping; - - if (!dumb_mode) { - -#ifdef __x86_64__ - simplify_trace((u64*)trace_bits); -#else - simplify_trace((u32*)trace_bits); -#endif /* ^__x86_64__ */ - - if (!has_new_bits(virgin_tmout)) return keeping; - - } - - unique_tmouts++; - - /* Before saving, we make sure that it's a genuine hang by re-running - the target with a more generous timeout (unless the default timeout - is already generous). */ - - if (exec_tmout < hang_tmout) { - - u8 new_fault; - write_to_testcase(mem, len); - new_fault = run_target(argv, hang_tmout); - - /* A corner case that one user reported bumping into: increasing the - timeout actually uncovers a crash. Make sure we don't discard it if - so. */ - - if (!stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash; - - if (stop_soon || new_fault != FAULT_TMOUT) return keeping; - - } - -#ifndef SIMPLE_FILES - - fn = alloc_printf("%s/hangs/id:%06llu,%s", out_dir, - unique_hangs, describe_op(0)); - -#else - - fn = alloc_printf("%s/hangs/id_%06llu", out_dir, - unique_hangs); - -#endif /* ^!SIMPLE_FILES */ - - unique_hangs++; - - last_hang_time = get_cur_time(); - - break; - - case FAULT_CRASH: - -keep_as_crash: - - /* This is handled in a manner roughly similar to timeouts, - except for slightly different limits and no need to re-run test - cases. */ - - total_crashes++; - - if (unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; - - if (!dumb_mode) { - -#ifdef __x86_64__ - simplify_trace((u64*)trace_bits); -#else - simplify_trace((u32*)trace_bits); -#endif /* ^__x86_64__ */ - - if (!has_new_bits(virgin_crash)) return keeping; - - } - - if (!unique_crashes) write_crash_readme(); - -#ifndef SIMPLE_FILES - - fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", out_dir, - unique_crashes, kill_signal, describe_op(0)); - -#else - - fn = alloc_printf("%s/crashes/id_%06llu_%02u", out_dir, unique_crashes, - kill_signal); - -#endif /* ^!SIMPLE_FILES */ - - unique_crashes++; - - last_crash_time = get_cur_time(); - last_crash_execs = total_execs; - - break; - - case FAULT_ERROR: FATAL("Unable to execute target application"); - - default: return keeping; - - } - - /* If we're here, we apparently want to save the crash or hang - test case, too. */ - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - ck_write(fd, mem, len, fn); - close(fd); - - ck_free(fn); - - return keeping; - -} - - -/* When resuming, try to find the queue position to start from. This makes sense - only when resuming, and when we can find the original fuzzer_stats. */ - -static u32 find_start_position(void) { - - static u8 tmp[4096]; /* Ought to be enough for anybody. */ - - u8 *fn, *off; - s32 fd, i; - u32 ret; - - if (!resuming_fuzz) return 0; - - if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); - else fn = alloc_printf("%s/../fuzzer_stats", in_dir); - - fd = open(fn, O_RDONLY); - ck_free(fn); - - if (fd < 0) return 0; - - i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ - close(fd); - - off = strstr((const char*)tmp, "cur_path : "); - if (!off) return 0; - - ret = atoi(off + 20); - if (ret >= queued_paths) ret = 0; - return ret; - -} - - -/* The same, but for timeouts. The idea is that when resuming sessions without - -t given, we don't want to keep auto-scaling the timeout over and over - again to prevent it from growing due to random flukes. */ - -static void find_timeout(void) { - - static u8 tmp[4096]; /* Ought to be enough for anybody. */ - - u8 *fn, *off; - s32 fd, i; - u32 ret; - - if (!resuming_fuzz) return; - - if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); - else fn = alloc_printf("%s/../fuzzer_stats", in_dir); - - fd = open(fn, O_RDONLY); - ck_free(fn); - - if (fd < 0) return; - - i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ - close(fd); - - off = strstr((const char*)tmp, "exec_timeout : "); - if (!off) return; - - ret = atoi(off + 20); - if (ret <= 4) return; - - exec_tmout = ret; - timeout_given = 3; - -} - - -/* Update stats file for unattended monitoring. */ - -static void write_stats_file(double bitmap_cvg, double stability, double eps) { - - static double last_bcvg, last_stab, last_eps; - static struct rusage usage; - - u8* fn = alloc_printf("%s/fuzzer_stats", out_dir); - s32 fd; - FILE* f; - - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_free(fn); - - f = fdopen(fd, "w"); - - if (!f) PFATAL("fdopen() failed"); - - /* Keep last values in case we're called from another context - where exec/sec stats and such are not readily available. */ - - if (!bitmap_cvg && !stability && !eps) { - bitmap_cvg = last_bcvg; - stability = last_stab; - eps = last_eps; - } else { - last_bcvg = bitmap_cvg; - last_stab = stability; - last_eps = eps; - } - - fprintf(f, "start_time : %llu\n" - "last_update : %llu\n" - "fuzzer_pid : %u\n" - "cycles_done : %llu\n" - "execs_done : %llu\n" - "total_vaild : %llu\n" - "execs_per_sec : %0.02f\n" - "paths_total : %u\n" - "paths_favored : %u\n" - "paths_found : %u\n" - "paths_imported : %u\n" - "max_depth : %u\n" - "cur_path : %u\n" /* Must match find_start_position() */ - "pending_favs : %u\n" - "pending_total : %u\n" - "variable_paths : %u\n" - "stability : %0.02f%%\n" - "bitmap_cvg : %0.02f%%\n" - "unique_crashes : %llu\n" - "unique_hangs : %llu\n" - "last_path : %llu\n" - "last_crash : %llu\n" - "last_hang : %llu\n" - "execs_since_crash : %llu\n" - "exec_timeout : %u\n" /* Must match find_timeout() */ - "afl_banner : %s\n" - "afl_version : " VERSION "\n" - "target_mode : %s%s%s%s%s%s%s\n" - "command_line : %s\n" - "slowest_exec_ms : %llu\n", - start_time / 1000, get_cur_time() / 1000, getpid(), - queue_cycle ? (queue_cycle - 1) : 0, total_execs, total_vaild, eps, - queued_paths, queued_favored, queued_discovered, queued_imported, - max_depth, current_entry, pending_favored, pending_not_fuzzed, - queued_variable, stability, bitmap_cvg, unique_crashes, - unique_hangs, last_path_time / 1000, last_crash_time / 1000, - last_hang_time / 1000, total_execs - last_crash_execs, - exec_tmout, use_banner, - qemu_mode ? "qemu " : "", dumb_mode ? " dumb " : "", - no_forkserver ? "no_forksrv " : "", crash_mode ? "crash " : "", - persistent_mode ? "persistent " : "", deferred_mode ? "deferred " : "", - (qemu_mode || dumb_mode || no_forkserver || crash_mode || - persistent_mode || deferred_mode) ? "" : "default", - orig_cmdline, slowest_exec_ms); - - fprintf(f, "mutate total : %llu\n", g_mutator.totalMutate_); - fprintf(f, "mutate failed : %llu\n", g_mutator.failedMutate_); - /* ignore errors */ - /* Get rss value from the children - We must have killed the forkserver process and called waitpid - before calling getrusage */ - if (getrusage(RUSAGE_CHILDREN, &usage)) { - WARNF("getrusage failed"); - } else if (usage.ru_maxrss == 0) { - fprintf(f, "peak_rss_mb : not available while afl is running\n"); - } else { -#ifdef __APPLE__ - fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss >> 20); -#else - fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss >> 10); -#endif /* ^__APPLE__ */ - } - - fclose(f); - -} - - -/* Update the plot file if there is a reason to. */ - -static void maybe_update_plot_file(double bitmap_cvg, double eps) { - - static u32 prev_qp, prev_pf, prev_pnf, prev_ce, prev_md; - static u64 prev_qc, prev_uc, prev_uh; - - if (prev_qp == queued_paths && prev_pf == pending_favored && - prev_pnf == pending_not_fuzzed && prev_ce == current_entry && - prev_qc == queue_cycle && prev_uc == unique_crashes && - prev_uh == unique_hangs && prev_md == max_depth) return; - - prev_qp = queued_paths; - prev_pf = pending_favored; - prev_pnf = pending_not_fuzzed; - prev_ce = current_entry; - prev_qc = queue_cycle; - prev_uc = unique_crashes; - prev_uh = unique_hangs; - prev_md = max_depth; - - /* Fields in the file: - - unix_time, cycles_done, cur_path, paths_total, paths_not_fuzzed, - favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, - execs_per_sec */ - - fprintf(plot_file, - "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, %llu, %llu\n", - get_cur_time() / 1000, queue_cycle - 1, current_entry, queued_paths, - pending_not_fuzzed, pending_favored, bitmap_cvg, unique_crashes, - unique_hangs, max_depth, eps, total_execs, total_vaild, seed_count); - - fflush(plot_file); - -} - - - -/* A helper function for maybe_delete_out_dir(), deleting all prefixed - files in a directory. */ - -static u8 delete_files(u8* path, u8* prefix) { - - DIR* d; - struct dirent* d_ent; - - d = opendir(path); - - if (!d) return 0; - - while ((d_ent = readdir(d))) { - - if (d_ent->d_name[0] != '.' && (!prefix || - !strncmp(d_ent->d_name, prefix, strlen(prefix)))) { - - u8* fname = alloc_printf("%s/%s", path, d_ent->d_name); - if (unlink(fname)) PFATAL("Unable to delete '%s'", fname); - ck_free(fname); - - } - - } - - closedir(d); - - return !!rmdir(path); - -} - - -/* Get the number of runnable processes, with some simple smoothing. */ - -static double get_runnable_processes(void) { - - static double res; - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) - - /* I don't see any portable sysctl or so that would quickly give us the - number of runnable processes; the 1-minute load average can be a - semi-decent approximation, though. */ - - if (getloadavg(&res, 1) != 1) return 0; - -#else - - /* On Linux, /proc/stat is probably the best way; load averages are - computed in funny ways and sometimes don't reflect extremely short-lived - processes well. */ - - FILE* f = fopen("/proc/stat", "r"); - u8 tmp[1024]; - u32 val = 0; - - if (!f) return 0; - - while (fgets(tmp, sizeof(tmp), f)) { - - if (!strncmp(tmp, "procs_running ", 14) || - !strncmp(tmp, "procs_blocked ", 14)) val += atoi(tmp + 14); - - } - - fclose(f); - - if (!res) { - - res = val; - - } else { - - res = res * (1.0 - 1.0 / AVG_SMOOTHING) + - ((double)val) * (1.0 / AVG_SMOOTHING); - - } - -#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ - - return res; - -} - - -/* Delete the temporary directory used for in-place session resume. */ - -static void nuke_resume_dir(void) { - - u8* fn; - - fn = alloc_printf("%s/_resume/.state/deterministic_done", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state/auto_extras", out_dir); - if (delete_files(fn, "auto_")) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state/redundant_edges", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state/variable_behavior", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume/.state", out_dir); - if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/_resume", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - return; - -dir_cleanup_failed: - - FATAL("_resume directory cleanup failed"); - -} - - -/* Delete fuzzer output directory if we recognize it as ours, if the fuzzer - is not currently running, and if the last run time isn't too great. */ - -static void maybe_delete_out_dir(void) { - - FILE* f; - u8 *fn = alloc_printf("%s/fuzzer_stats", out_dir); - - /* See if the output directory is locked. If yes, bail out. If not, - create a lock that will persist for the lifetime of the process - (this requires leaving the descriptor open).*/ - - out_dir_fd = open(out_dir, O_RDONLY); - if (out_dir_fd < 0) PFATAL("Unable to open '%s'", out_dir); - -#ifndef __sun - - if (flock(out_dir_fd, LOCK_EX | LOCK_NB) && errno == EWOULDBLOCK) { - - SAYF("\n" cLRD "[-] " cRST - "Looks like the job output directory is being actively used by another\n" - " instance of afl-fuzz. You will need to choose a different %s\n" - " or stop the other process first.\n", - sync_id ? "fuzzer ID" : "output location"); - - FATAL("Directory '%s' is in use", out_dir); - - } - -#endif /* !__sun */ - - f = fopen(fn, "r"); - - if (f) { - - u64 start_time, last_update; - - if (fscanf(f, "start_time : %llu\n" - "last_update : %llu\n", &start_time, &last_update) != 2) - FATAL("Malformed data in '%s'", fn); - - fclose(f); - - /* Let's see how much work is at stake. */ - - if (!in_place_resume && last_update - start_time > OUTPUT_GRACE * 60) { - - SAYF("\n" cLRD "[-] " cRST - "The job output directory already exists and contains the results of more\n" - " than %u minutes worth of fuzzing. To avoid data loss, afl-fuzz will *NOT*\n" - " automatically delete this data for you.\n\n" - - " If you wish to start a new session, remove or rename the directory manually,\n" - " or specify a different output location for this job. To resume the old\n" - " session, put '-' as the input directory in the command line ('-i -') and\n" - " try again.\n", OUTPUT_GRACE); - - FATAL("At-risk data found in '%s'", out_dir); - - } - - } - - ck_free(fn); - - /* The idea for in-place resume is pretty simple: we temporarily move the old - queue/ to a new location that gets deleted once import to the new queue/ - is finished. If _resume/ already exists, the current queue/ may be - incomplete due to an earlier abort, so we want to use the old _resume/ - dir instead, and we let rename() fail silently. */ - - if (in_place_resume) { - - u8* orig_q = alloc_printf("%s/queue", out_dir); - - in_dir = alloc_printf("%s/_resume", out_dir); - - rename(orig_q, in_dir); /* Ignore errors */ - - OKF("Output directory exists, will attempt session resume."); - - ck_free(orig_q); - - } else { - - OKF("Output directory exists but deemed OK to reuse."); - - } - - ACTF("Deleting old session data..."); - - /* Okay, let's get the ball rolling! First, we need to get rid of the entries - in /.synced/.../id:*, if any are present. */ - - if (!in_place_resume) { - - fn = alloc_printf("%s/.synced", out_dir); - if (delete_files(fn, NULL)) goto dir_cleanup_failed; - ck_free(fn); - - } - - /* Next, we need to clean up /queue/.state/ subdirectories: */ - - fn = alloc_printf("%s/queue/.state/deterministic_done", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue/.state/auto_extras", out_dir); - if (delete_files(fn, "auto_")) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue/.state/redundant_edges", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue/.state/variable_behavior", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - /* Then, get rid of the .state subdirectory itself (should be empty by now) - and everything matching /queue/id:*. */ - - fn = alloc_printf("%s/queue/.state", out_dir); - if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/queue", out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - /* All right, let's do /crashes/id:* and /hangs/id:*. */ - - if (!in_place_resume) { - - fn = alloc_printf("%s/crashes/README.txt", out_dir); - unlink(fn); /* Ignore errors */ - ck_free(fn); - - } - - fn = alloc_printf("%s/crashes", out_dir); - - /* Make backup of the crashes directory if it's not empty and if we're - doing in-place resume. */ - - if (in_place_resume && rmdir(fn)) { - - time_t cur_t = time(0); - struct tm* t = localtime(&cur_t); - -#ifndef SIMPLE_FILES - - u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#else - - u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#endif /* ^!SIMPLE_FILES */ - - rename(fn, nfn); /* Ignore errors. */ - ck_free(nfn); - - } - - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/hangs", out_dir); - - /* Backup hangs, too. */ - - if (in_place_resume && rmdir(fn)) { - - time_t cur_t = time(0); - struct tm* t = localtime(&cur_t); - -#ifndef SIMPLE_FILES - - u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#else - - u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - -#endif /* ^!SIMPLE_FILES */ - - rename(fn, nfn); /* Ignore errors. */ - ck_free(nfn); - - } - - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; - ck_free(fn); - - /* And now, for some finishing touches. */ - - fn = alloc_printf("%s/.cur_input", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - fn = alloc_printf("%s/fuzz_bitmap", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - if (!in_place_resume) { - fn = alloc_printf("%s/fuzzer_stats", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - } - - fn = alloc_printf("%s/plot_data", out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; - ck_free(fn); - - OKF("Output dir cleanup successful."); - - /* Wow... is that all? If yes, celebrate! */ - - return; - -dir_cleanup_failed: - - SAYF("\n" cLRD "[-] " cRST - "Whoops, the fuzzer tried to reuse your output directory, but bumped into\n" - " some files that shouldn't be there or that couldn't be removed - so it\n" - " decided to abort! This happened while processing this path:\n\n" - - " %s\n\n" - " Please examine and manually delete the files, or specify a different\n" - " output location for the tool.\n", fn); - - FATAL("Output directory cleanup failed"); - -} - - -static void check_term_size(void); - - -/* A spiffy retro stats screen! This is called every stats_update_freq - execve() calls, plus in several other circumstances. */ - -static void show_stats(void) { - - static u64 last_stats_ms, last_plot_ms, last_ms, last_execs; - static double avg_exec; - double t_byte_ratio, stab_ratio; - - u64 cur_ms; - u32 t_bytes, t_bits; - - u32 banner_len, banner_pad; - u8 tmp[256]; - - cur_ms = get_cur_time(); - - /* If not enough time has passed since last UI update, bail out. */ - - if (cur_ms - last_ms < 1000 / UI_TARGET_HZ) return; - - /* Check if we're past the 10 minute mark. */ - - if (cur_ms - start_time > 10 * 60 * 1000) run_over10m = 1; - - /* Calculate smoothed exec speed stats. */ - - if (!last_execs) { - - avg_exec = ((double)total_execs) * 1000 / (cur_ms - start_time); - - } else { - - double cur_avg = ((double)(total_execs - last_execs)) * 1000 / - (cur_ms - last_ms); - - /* If there is a dramatic (5x+) jump in speed, reset the indicator - more quickly. */ - - if (cur_avg * 5 < avg_exec || cur_avg / 5 > avg_exec) - avg_exec = cur_avg; - - avg_exec = avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + - cur_avg * (1.0 / AVG_SMOOTHING); - - } - - last_ms = cur_ms; - last_execs = total_execs; - - /* Tell the callers when to contact us (as measured in execs). */ - - stats_update_freq = avg_exec / (UI_TARGET_HZ * 10); - if (!stats_update_freq) stats_update_freq = 1; - - /* Do some bitmap stats. */ - - t_bytes = count_non_255_bytes(virgin_bits); - t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE; - - if (t_bytes) - stab_ratio = 100 - ((double)var_byte_count) * 100 / t_bytes; - else - stab_ratio = 100; - - /* Roughly every minute, update fuzzer stats and save auto tokens. */ - - if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) { - - last_stats_ms = cur_ms; - write_stats_file(t_byte_ratio, stab_ratio, avg_exec); - save_auto(); - write_bitmap(); - - } - - /* Every now and then, write plot data. */ - - if (cur_ms - last_plot_ms > PLOT_UPDATE_SEC * 1000) { - - last_plot_ms = cur_ms; - maybe_update_plot_file(t_byte_ratio, avg_exec); - - } - - /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ - - if (!dumb_mode && cycles_wo_finds > 100 && !pending_not_fuzzed && - getenv("AFL_EXIT_WHEN_DONE")) stop_soon = 2; - - if (total_crashes && getenv("AFL_BENCH_UNTIL_CRASH")) stop_soon = 2; - - /* If we're not on TTY, bail out. */ - - if (not_on_tty) return; - - /* Compute some mildly useful bitmap stats. */ - - t_bits = (MAP_SIZE << 3) - count_bits(virgin_bits); - - /* Now, for the visuals... */ - - if (clear_screen) { - - SAYF(TERM_CLEAR CURSOR_HIDE); - clear_screen = 0; - - check_term_size(); - - } - - SAYF(TERM_HOME); - - if (term_too_small) { - - SAYF(cBRI "Your terminal is too small to display the UI.\n" - "Please resize terminal window to at least 80x25.\n" cRST); - - return; - - } - - /* Let's start by drawing a centered banner. */ - - banner_len = (crash_mode ? 24 : 22) + strlen(VERSION) + strlen(use_banner); - banner_pad = (80 - banner_len) / 2; - memset(tmp, ' ', banner_pad); - - sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN - " (%s)", crash_mode ? cPIN "peruvian were-rabbit" : - cYEL "american fuzzy lop", use_banner); - - SAYF("\n%s\n\n", tmp); - - /* "Handy" shortcuts for drawing boxes... */ - -#define bSTG bSTART cGRA -#define bH2 bH bH -#define bH5 bH2 bH2 bH -#define bH10 bH5 bH5 -#define bH20 bH10 bH10 -#define bH30 bH20 bH10 -#define SP5 " " -#define SP10 SP5 SP5 -#define SP20 SP10 SP10 - - /* Lord, forgive me this. */ - - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH2 bHB - bH bSTOP cCYA " overall results " bSTG bH5 bRT "\n"); - - if (dumb_mode) { - - strcpy(tmp, cRST); - - } else { - - u64 min_wo_finds = (cur_ms - last_path_time) / 1000 / 60; - - /* First queue cycle: don't stop now! */ - if (queue_cycle == 1 || min_wo_finds < 15) strcpy(tmp, cMGN); else - - /* Subsequent cycles, but we're still making finds. */ - if (cycles_wo_finds < 25 || min_wo_finds < 30) strcpy(tmp, cYEL); else - - /* No finds for a long time and no test cases to try. */ - if (cycles_wo_finds > 100 && !pending_not_fuzzed && min_wo_finds > 120) - strcpy(tmp, cLGN); - - /* Default: cautiously OK to stop? */ - else strcpy(tmp, cLBL); - - } - - SAYF(bV bSTOP " run time : " cRST "%-34s " bSTG bV bSTOP - " cycles done : %s%-5s " bSTG bV "\n", - DTD(cur_ms, start_time), tmp, DI(queue_cycle - 1)); - - /* We want to warn people about not seeing new paths after a full cycle, - except when resuming fuzzing or running in non-instrumented mode. */ - - if (!dumb_mode && (last_path_time || resuming_fuzz || queue_cycle == 1 || - in_bitmap || crash_mode)) { - - SAYF(bV bSTOP " last new path : " cRST "%-34s ", - DTD(cur_ms, last_path_time)); - - } else { - - if (dumb_mode) - - SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST - " (non-instrumented mode) "); - - else - - SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD - "(odd, check syntax!) "); - - } - - SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n", - DI(queued_paths)); - - /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH - limit with a '+' appended to the count. */ - - sprintf(tmp, "%s%s", DI(unique_crashes), - (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); - - SAYF(bV bSTOP " last uniq crash : " cRST "%-34s " bSTG bV bSTOP - " uniq crashes : %s%-6s " bSTG bV "\n", - DTD(cur_ms, last_crash_time), unique_crashes ? cLRD : cRST, - tmp); - - sprintf(tmp, "%s%s", DI(unique_hangs), - (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); - - SAYF(bV bSTOP " last uniq hang : " cRST "%-34s " bSTG bV bSTOP - " uniq hangs : " cRST "%-6s " bSTG bV "\n", - DTD(cur_ms, last_hang_time), tmp); - - SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH20 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bH bVL "\n"); - - /* This gets funny because we want to print several variable-length variables - together, but then cram them into a fixed-width field - so we need to - put them in a temporary buffer first. */ - - sprintf(tmp, "%s%s (%0.02f%%)", DI(current_entry), - queue_cur->favored ? "" : "*", - ((double)current_entry * 100) / queued_paths); - - SAYF(bV bSTOP " now processing : " cRST "%-17s " bSTG bV bSTOP, tmp); - - sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * - 100 / MAP_SIZE, t_byte_ratio); - - SAYF(" map density : %s%-21s " bSTG bV "\n", t_byte_ratio > 70 ? cLRD : - ((t_bytes < 200 && !dumb_mode) ? cPIN : cRST), tmp); - - sprintf(tmp, "%s (%0.02f%%)", DI(cur_skipped_paths), - ((double)cur_skipped_paths * 100) / queued_paths); - - SAYF(bV bSTOP " paths timed out : " cRST "%-17s " bSTG bV, tmp); - - sprintf(tmp, "%0.02f bits/tuple", - t_bytes ? (((double)t_bits) / t_bytes) : 0); - - SAYF(bSTOP " count coverage : " cRST "%-21s " bSTG bV "\n", tmp); - - SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH20 bX bH bSTOP cCYA - " findings in depth " bSTG bH20 bVL "\n"); - - /* Yeah... it's still going on... halp? */ - - sprintf(tmp, "%s (%0.02f%%)", DI(total_vaild), - total_execs ? ((double)total_vaild) * 100 / total_execs : (double)0); - - SAYF(bV bSTOP " total vaild : " cRST "%-21s " bSTG bV bSTOP, tmp); - - sprintf(tmp, "%s (%0.02f%%)", DI(queued_favored), - ((double)queued_favored) * 100 / queued_paths); - - SAYF(" favored paths : " cRST "%-22s " bSTG bV "\n", tmp); - - if (!stage_max) { - - sprintf(tmp, "%s/-", DI(stage_cur)); - - } else { - - sprintf(tmp, "%s/%s (%0.02f%%)", DI(stage_cur), DI(stage_max), - ((double)stage_cur) * 100 / stage_max); - - } - - SAYF(bV bSTOP " stage execs : " cRST "%-21s " bSTG bV bSTOP, tmp); - - sprintf(tmp, "%s (%0.02f%%)", DI(queued_with_cov), - ((double)queued_with_cov) * 100 / queued_paths); - - SAYF(" new edges on : " cRST "%-22s " bSTG bV "\n", tmp); - - sprintf(tmp, "%s (%s%s unique)", DI(total_crashes), DI(unique_crashes), - (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); - - if (crash_mode) { - - SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP - " new crashes : %s%-22s " bSTG bV "\n", DI(total_execs), - unique_crashes ? cLRD : cRST, tmp); - - } else { - - SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP - " total crashes : %s%-22s " bSTG bV "\n", DI(total_execs), - unique_crashes ? cLRD : cRST, tmp); - - } - - /* Show a warning about slow execution. */ - - if (avg_exec < 100) { - - sprintf(tmp, "%s/sec (%s)", DF(avg_exec), avg_exec < 20 ? - "zzzz..." : "slow!"); - - SAYF(bV bSTOP " exec speed : " cLRD "%-21s ", tmp); - - } else { - - sprintf(tmp, "%s/sec", DF(avg_exec)); - SAYF(bV bSTOP " exec speed : " cRST "%-21s ", tmp); - - } - - sprintf(tmp, "%s (%s%s unique)", DI(total_tmouts), DI(unique_tmouts), - (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); - - SAYF (bSTG bV bSTOP " total tmouts : " cRST "%-22s " bSTG bV "\n", tmp); - - /* Aaaalmost there... hold on! */ - - SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH bHT bH10 - bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bH bVL "\n"); - - if (skip_deterministic) { - - strcpy(tmp, "n/a, n/a, n/a"); - - } else { - - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_FLIP1]), DI(stage_cycles[STAGE_FLIP1]), - DI(stage_finds[STAGE_FLIP2]), DI(stage_cycles[STAGE_FLIP2]), - DI(stage_finds[STAGE_FLIP4]), DI(stage_cycles[STAGE_FLIP4])); - - } - - SAYF(bV bSTOP " bit flips : " cRST "%-37s " bSTG bV bSTOP " levels : " - cRST "%-10s " bSTG bV "\n", tmp, DI(max_depth)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_FLIP8]), DI(stage_cycles[STAGE_FLIP8]), - DI(stage_finds[STAGE_FLIP16]), DI(stage_cycles[STAGE_FLIP16]), - DI(stage_finds[STAGE_FLIP32]), DI(stage_cycles[STAGE_FLIP32])); - - SAYF(bV bSTOP " byte flips : " cRST "%-37s " bSTG bV bSTOP " pending : " - cRST "%-10s " bSTG bV "\n", tmp, DI(pending_not_fuzzed)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_ARITH8]), DI(stage_cycles[STAGE_ARITH8]), - DI(stage_finds[STAGE_ARITH16]), DI(stage_cycles[STAGE_ARITH16]), - DI(stage_finds[STAGE_ARITH32]), DI(stage_cycles[STAGE_ARITH32])); - - SAYF(bV bSTOP " arithmetics : " cRST "%-37s " bSTG bV bSTOP " pend fav : " - cRST "%-10s " bSTG bV "\n", tmp, DI(pending_favored)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_INTEREST8]), DI(stage_cycles[STAGE_INTEREST8]), - DI(stage_finds[STAGE_INTEREST16]), DI(stage_cycles[STAGE_INTEREST16]), - DI(stage_finds[STAGE_INTEREST32]), DI(stage_cycles[STAGE_INTEREST32])); - - SAYF(bV bSTOP " known ints : " cRST "%-37s " bSTG bV bSTOP " own finds : " - cRST "%-10s " bSTG bV "\n", tmp, DI(queued_discovered)); - - if (!skip_deterministic) - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_EXTRAS_UO]), DI(stage_cycles[STAGE_EXTRAS_UO]), - DI(stage_finds[STAGE_EXTRAS_UI]), DI(stage_cycles[STAGE_EXTRAS_UI]), - DI(stage_finds[STAGE_EXTRAS_AO]), DI(stage_cycles[STAGE_EXTRAS_AO])); - - SAYF(bV bSTOP " dictionary : " cRST "%-37s " bSTG bV bSTOP - " imported : " cRST "%-10s " bSTG bV "\n", tmp, - sync_id ? DI(queued_imported) : (u8*)"n/a"); - - sprintf(tmp, "%s/%s, %s/%s", - DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), - DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE])); - - SAYF(bV bSTOP " havoc : " cRST "%-37s " bSTG bV bSTOP, tmp); - - if (t_bytes) sprintf(tmp, "%0.02f%%", stab_ratio); - else strcpy(tmp, "n/a"); - - SAYF(" stability : %s%-10s " bSTG bV "\n", (stab_ratio < 85 && var_byte_count > 40) - ? cLRD : ((queued_variable && (!persistent_mode || var_byte_count > 20)) - ? cMGN : cRST), tmp); - - if (!bytes_trim_out) { - - sprintf(tmp, "n/a, "); - - } else { - - sprintf(tmp, "%0.02f%%/%s, ", - ((double)(bytes_trim_in - bytes_trim_out)) * 100 / bytes_trim_in, - DI(trim_execs)); - - } - - if (!blocks_eff_total) { - - u8 tmp2[128]; - - sprintf(tmp2, "n/a"); - strcat(tmp, tmp2); - - } else { - - u8 tmp2[128]; - - sprintf(tmp2, "%0.02f%%", - ((double)(blocks_eff_total - blocks_eff_select)) * 100 / - blocks_eff_total); - - strcat(tmp, tmp2); - - } - - SAYF(bV bSTOP " trim : " cRST "%-37s " bSTG bVR bH20 bH2 bH2 bRB "\n" - bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1, tmp); - - /* Provide some CPU utilization stats. */ - - if (cpu_core_count) { - - double cur_runnable = get_runnable_processes(); - u32 cur_utilization = cur_runnable * 100 / cpu_core_count; - - u8* cpu_color = cCYA; - - /* If we could still run one or more processes, use green. */ - - if (cpu_core_count > 1 && cur_runnable + 1 <= cpu_core_count) - cpu_color = cLGN; - - /* If we're clearly oversubscribed, use red. */ - - if (!no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD; - -#ifdef HAVE_AFFINITY - - if (cpu_aff >= 0) { - - SAYF(SP10 cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, - MIN(cpu_aff, 999), cpu_color, - MIN(cur_utilization, 999)); - - } else { - - SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, - cpu_color, MIN(cur_utilization, 999)); - - } - -#else - - SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, - cpu_color, MIN(cur_utilization, 999)); - -#endif /* ^HAVE_AFFINITY */ - - } else SAYF("\r"); - - /* Hallelujah! */ - - fflush(0); - - if (get_cur_time() - last_save_time > 60 * 60 * 1000) { - u8* fn = alloc_printf("%s/coverage_statistics", out_dir); - - FILE* fd = fopen(fn, "a+"); - - if (!fd) PFATAL("Unable to create '%s'", fn); - - ck_free(fn); - - fprintf(fd, "%d\t%d\t%d (%0.02f%%)\t%d(%0.02f%%)\n", (unsigned int)((get_cur_time() - start_time) / (60 * 60 * 1000)), queued_paths, total_vaild, total_execs ? ((double)total_vaild) * 100 / total_execs : (double)0, t_bytes, t_byte_ratio); - - fclose(fd); - - last_save_time = get_cur_time(); - } - -} - - -/* Display quick statistics at the end of processing the input directory, - plus a bunch of warnings. Some calibration stuff also ended up here, - along with several hardcoded constants. Maybe clean up eventually. */ - -static void show_init_stats(void) { - - struct queue_entry* q = queue; - u32 min_bits = 0, max_bits = 0; - u64 min_us = 0, max_us = 0; - u64 avg_us = 0; - u32 max_len = 0; - - if (total_cal_cycles) avg_us = total_cal_us / total_cal_cycles; - - while (q) { - - if (!min_us || q->exec_us < min_us) min_us = q->exec_us; - if (q->exec_us > max_us) max_us = q->exec_us; - - if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size; - if (q->bitmap_size > max_bits) max_bits = q->bitmap_size; - - if (q->len > max_len) max_len = q->len; - - q = q->next; - - } - - SAYF("\n"); - - if (avg_us > (qemu_mode ? 50000 : 10000)) - WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.txt.", - doc_path); - - /* Let's keep things moving with slow binaries. */ - - if (avg_us > 50000) havoc_div = 10; /* 0-19 execs/sec */ - else if (avg_us > 20000) havoc_div = 5; /* 20-49 execs/sec */ - else if (avg_us > 10000) havoc_div = 2; /* 50-100 execs/sec */ - - if (!resuming_fuzz) { - - if (max_len > 50 * 1024) - WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.txt!", - DMS(max_len), doc_path); - else if (max_len > 10 * 1024) - WARNF("Some test cases are big (%s) - see %s/perf_tips.txt.", - DMS(max_len), doc_path); - - if (useless_at_start && !in_bitmap) - WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); - - if (queued_paths > 100) - WARNF(cLRD "You probably have far too many input files! Consider trimming down."); - else if (queued_paths > 20) - WARNF("You have lots of input files; try starting small."); - - } - - OKF("Here are some useful stats:\n\n" - - cGRA " Test case count : " cRST "%u favored, %u variable, %u total\n" - cGRA " Bitmap range : " cRST "%u to %u bits (average: %0.02f bits)\n" - cGRA " Exec timing : " cRST "%s to %s us (average: %s us)\n", - queued_favored, queued_variable, queued_paths, min_bits, max_bits, - ((double)total_bitmap_size) / (total_bitmap_entries ? total_bitmap_entries : 1), - DI(min_us), DI(max_us), DI(avg_us)); - - if (!timeout_given) { - - /* Figure out the appropriate timeout. The basic idea is: 5x average or - 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. - - If the program is slow, the multiplier is lowered to 2x or 3x, because - random scheduler jitter is less likely to have any impact, and because - our patience is wearing thin =) */ - - if (avg_us > 50000) exec_tmout = avg_us * 2 / 1000; - else if (avg_us > 10000) exec_tmout = avg_us * 3 / 1000; - else exec_tmout = avg_us * 5 / 1000; - - exec_tmout = MAX(exec_tmout, max_us / 1000); - exec_tmout = (exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; - - if (exec_tmout > EXEC_TIMEOUT) exec_tmout = EXEC_TIMEOUT; - - ACTF("No -t option specified, so I'll use exec timeout of %u ms.", - exec_tmout); - - timeout_given = 1; - - } else if (timeout_given == 3) { - - ACTF("Applying timeout settings from resumed session (%u ms).", exec_tmout); - - } - - /* In dumb mode, re-running every timing out test case with a generous time - limit is very expensive, so let's select a more conservative default. */ - - if (dumb_mode && !getenv("AFL_HANG_TMOUT")) - hang_tmout = MIN(EXEC_TIMEOUT, exec_tmout * 2 + 100); - - OKF("All set and ready to roll!"); - -} - - -/* Find first power of two greater or equal to val (assuming val under - 2^31). */ - -static u32 next_p2(u32 val) { - - u32 ret = 1; - while (val > ret) ret <<= 1; - return ret; - -} - - -/* Trim all new test cases to save cycles when doing deterministic checks. The - trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of - file size, to keep the stage short and sweet. */ - -static u8 trim_case(char** argv, struct queue_entry* q, u8* in_buf) { - - static u8 tmp[64]; - static u8 clean_trace[MAP_SIZE]; - - u8 needs_write = 0, fault = 0; - u32 trim_exec = 0; - u32 remove_len; - u32 len_p2; - - /* Although the trimmer will be less useful when variable behavior is - detected, it will still work to some extent, so we don't check for - this. */ - - if (q->len < 5) return 0; - - stage_name = tmp; - bytes_trim_in += q->len; - - /* Select initial chunk len, starting with large steps. */ - - len_p2 = next_p2(q->len); - - remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES); - - /* Continue until the number of steps gets too high or the stepover - gets too small. */ - - while (remove_len >= MAX(len_p2 / TRIM_END_STEPS, TRIM_MIN_BYTES)) { - - u32 remove_pos = remove_len; - - sprintf(tmp, "trim %s/%s", DI(remove_len), DI(remove_len)); - - stage_cur = 0; - stage_max = q->len / remove_len; - - while (remove_pos < q->len) { - - u32 trim_avail = MIN(remove_len, q->len - remove_pos); - u32 cksum; - - write_with_gap(in_buf, q->len, remove_pos, trim_avail); - - fault = run_target(argv, exec_tmout); - trim_execs++; - - if (stop_soon || fault == FAULT_ERROR) goto abort_trimming; - - /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ - - cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); - - /* If the deletion had no impact on the trace, make it permanent. This - isn't perfect for variable-path inputs, but we're just making a - best-effort pass, so it's not a big deal if we end up with false - negatives every now and then. */ - - if (cksum == q->exec_cksum) { - - u32 move_tail = q->len - remove_pos - trim_avail; - - q->len -= trim_avail; - len_p2 = next_p2(q->len); - - memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, - move_tail); - - /* Let's save a clean trace, which will be needed by - update_bitmap_score once we're done with the trimming stuff. */ - - if (!needs_write) { - - needs_write = 1; - memcpy(clean_trace, trace_bits, MAP_SIZE); - - } - - } else remove_pos += remove_len; - - /* Since this can be slow, update the screen every now and then. */ - - if (!(trim_exec++ % stats_update_freq)) show_stats(); - stage_cur++; - - } - - remove_len >>= 1; - - } - - /* If we have made changes to in_buf, we also need to update the on-disk - version of the test case. */ - - if (needs_write) { - - s32 fd; - - unlink(q->fname); /* ignore errors */ - - fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", q->fname); - - ck_write(fd, in_buf, q->len, q->fname); - close(fd); - - memcpy(trace_bits, clean_trace, MAP_SIZE); - update_bitmap_score(q); - - } - -abort_trimming: - - bytes_trim_out += q->len; - return fault; - -} - -int num = 0; -/* Write a modified test case, run program, process results. Handle - error conditions, returning 1 if it's time to bail out. This is - a helper function for fuzz_one(). */ - -EXP_ST u8 common_fuzz_stuff(char** argv, const u8* out_buf, u32 len) { - - u8 fault; - u8 tmp_vaild_flag; - - //cout << num ++ << ":" << out_buf << endl; - if (post_handler) { - - out_buf = post_handler(out_buf, &len); - if (!out_buf || !len) return 0; - - } - write_to_testcase(out_buf, len); - - fault = run_target(argv, exec_tmout); - - tmp_vaild_flag = vaild_flag; - - if (stop_soon) return 1; - - if (fault == FAULT_TMOUT) { - - if (subseq_tmouts++ > TMOUT_LIMIT) { - cur_skipped_paths++; - return 1; - } - - } else subseq_tmouts = 0; - - /* Users can hit us with SIGUSR1 to request the current input - to be abandoned. */ - - if (skip_requested) { - - skip_requested = 0; - cur_skipped_paths++; - return 1; - - } - - /* This handles FAULT_ERROR for us: */ - //cout << num ++ << ":" << out_buf << endl; - int should_keep = save_if_interesting(argv, out_buf, len, fault); - queued_discovered += (should_keep == 1 || should_keep == 2); - - g_mutator.update_status(g_current_input, should_keep, tmp_vaild_flag); - - //cout << "OK" << endl; - if (!(stage_cur % stats_update_freq) || stage_cur + 1 == stage_max) - show_stats(); - - return 0; - -} - - -/* Helper to choose random block len for block operations in fuzz_one(). - Doesn't return zero, provided that max_len is > 0. */ - -static u32 choose_block_len(u32 limit) { - - u32 min_value, max_value; - u32 rlim = MIN(queue_cycle, 3); - - if (!run_over10m) rlim = 1; - - switch (UR(rlim)) { - - case 0: min_value = 1; - max_value = HAVOC_BLK_SMALL; - break; - - case 1: min_value = HAVOC_BLK_SMALL; - max_value = HAVOC_BLK_MEDIUM; - break; - - default: - - if (UR(10)) { - - min_value = HAVOC_BLK_MEDIUM; - max_value = HAVOC_BLK_LARGE; - - } else { - - min_value = HAVOC_BLK_LARGE; - max_value = HAVOC_BLK_XL; - - } - - } - - if (min_value >= limit) min_value = 1; - - return min_value + UR(MIN(max_value, limit) - min_value + 1); - -} - - -/* Calculate case desirability score to adjust the length of havoc fuzzing. - A helper function for fuzz_one(). Maybe some of these constants should - go into config.h. */ - -static u32 calculate_score(struct queue_entry* q) { - - u32 avg_exec_us = total_cal_us / (total_cal_cycles+1); - u32 avg_bitmap_size = total_bitmap_size / (total_bitmap_entries+1); - u32 perf_score = 100; - - /* Adjust score based on execution speed of this path, compared to the - global average. Multiplier ranges from 0.1x to 3x. Fast inputs are - less expensive to fuzz, so we're giving them more air time. */ - - if (q->exec_us * 0.1 > avg_exec_us) perf_score = 10; - else if (q->exec_us * 0.25 > avg_exec_us) perf_score = 25; - else if (q->exec_us * 0.5 > avg_exec_us) perf_score = 50; - else if (q->exec_us * 0.75 > avg_exec_us) perf_score = 75; - else if (q->exec_us * 4 < avg_exec_us) perf_score = 300; - else if (q->exec_us * 3 < avg_exec_us) perf_score = 200; - else if (q->exec_us * 2 < avg_exec_us) perf_score = 150; - - /* Adjust score based on bitmap size. The working theory is that better - coverage translates to better targets. Multiplier from 0.25x to 3x. */ - - if (q->bitmap_size * 0.3 > avg_bitmap_size) perf_score *= 3; - else if (q->bitmap_size * 0.5 > avg_bitmap_size) perf_score *= 2; - else if (q->bitmap_size * 0.75 > avg_bitmap_size) perf_score *= 1.5; - else if (q->bitmap_size * 3 < avg_bitmap_size) perf_score *= 0.25; - else if (q->bitmap_size * 2 < avg_bitmap_size) perf_score *= 0.5; - else if (q->bitmap_size * 1.5 < avg_bitmap_size) perf_score *= 0.75; - - /* Adjust score based on handicap. Handicap is proportional to how late - in the game we learned about this path. Latecomers are allowed to run - for a bit longer until they catch up with the rest. */ - - if (q->handicap >= 4) { - - perf_score *= 4; - q->handicap -= 4; - - } else if (q->handicap) { - - perf_score *= 2; - q->handicap--; - - } - - /* Final adjustment based on input depth, under the assumption that fuzzing - deeper test cases is more likely to reveal stuff that can't be - discovered with traditional fuzzers. */ - - switch (q->depth) { - - case 0 ... 3: break; - case 4 ... 7: perf_score *= 2; break; - case 8 ... 13: perf_score *= 3; break; - case 14 ... 25: perf_score *= 4; break; - default: perf_score *= 5; - - } - - /* Make sure that we don't go over limit. */ - - if (perf_score > HAVOC_MAX_MULT * 100) perf_score = HAVOC_MAX_MULT * 100; - - return perf_score; - -} - - -/* Helper function to see if a particular change (xor_val = old ^ new) could - be a product of deterministic bit flips with the lengths and stepovers - attempted by afl-fuzz. This is used to avoid dupes in some of the - deterministic fuzzing operations that follow bit flips. We also - return 1 if xor_val is zero, which implies that the old and attempted new - values are identical and the exec would be a waste of time. */ - -static u8 could_be_bitflip(u32 xor_val) { - - u32 sh = 0; - - if (!xor_val) return 1; - - /* Shift left until first bit set. */ - - while (!(xor_val & 1)) { sh++; xor_val >>= 1; } - - /* 1-, 2-, and 4-bit patterns are OK anywhere. */ - - if (xor_val == 1 || xor_val == 3 || xor_val == 15) return 1; - - /* 8-, 16-, and 32-bit patterns are OK only if shift factor is - divisible by 8, since that's the stepover for these ops. */ - - if (sh & 7) return 0; - - if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) - return 1; - - return 0; - -} - - -/* Helper function to see if a particular value is reachable through - arithmetic operations. Used for similar purposes. */ - -static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { - - u32 i, ov = 0, nv = 0, diffs = 0; - - if (old_val == new_val) return 1; - - /* See if one-byte adjustments to any byte could produce this result. */ - - for (i = 0; i < blen; i++) { - - u8 a = old_val >> (8 * i), - b = new_val >> (8 * i); - - if (a != b) { diffs++; ov = a; nv = b; } - - } - - /* If only one byte differs and the values are within range, return 1. */ - - if (diffs == 1) { - - if ((u8)(ov - nv) <= ARITH_MAX || - (u8)(nv - ov) <= ARITH_MAX) return 1; - - } - - if (blen == 1) return 0; - - /* See if two-byte adjustments to any byte would produce this result. */ - - diffs = 0; - - for (i = 0; i < blen / 2; i++) { - - u16 a = old_val >> (16 * i), - b = new_val >> (16 * i); - - if (a != b) { diffs++; ov = a; nv = b; } - - } - - /* If only one word differs and the values are within range, return 1. */ - - if (diffs == 1) { - - if ((u16)(ov - nv) <= ARITH_MAX || - (u16)(nv - ov) <= ARITH_MAX) return 1; - - ov = SWAP16(ov); nv = SWAP16(nv); - - if ((u16)(ov - nv) <= ARITH_MAX || - (u16)(nv - ov) <= ARITH_MAX) return 1; - - } - - /* Finally, let's do the same thing for dwords. */ - - if (blen == 4) { - - if ((u32)(old_val - new_val) <= ARITH_MAX || - (u32)(new_val - old_val) <= ARITH_MAX) return 1; - - new_val = SWAP32(new_val); - old_val = SWAP32(old_val); - - if ((u32)(old_val - new_val) <= ARITH_MAX || - (u32)(new_val - old_val) <= ARITH_MAX) return 1; - - } - - return 0; - -} - - - -/* Last but not least, a similar helper to see if insertion of an - interesting integer is redundant given the insertions done for - shorter blen. The last param (check_le) is set if the caller - already executed LE insertion for current blen and wants to see - if BE variant passed in new_val is unique. */ - -static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { - - u32 i, j; - - if (old_val == new_val) return 1; - - /* See if one-byte insertions from interesting_8 over old_val could - produce new_val. */ - - for (i = 0; i < blen; i++) { - - for (j = 0; j < sizeof(interesting_8); j++) { - - u32 tval = (old_val & ~(0xff << (i * 8))) | - (((u8)interesting_8[j]) << (i * 8)); - - if (new_val == tval) return 1; - - } - - } - - /* Bail out unless we're also asked to examine two-byte LE insertions - as a preparation for BE attempts. */ - - if (blen == 2 && !check_le) return 0; - - /* See if two-byte insertions over old_val could give us new_val. */ - - for (i = 0; i < blen - 1; i++) { - - for (j = 0; j < sizeof(interesting_16) / 2; j++) { - - u32 tval = (old_val & ~(0xffff << (i * 8))) | - (((u16)interesting_16[j]) << (i * 8)); - - if (new_val == tval) return 1; - - /* Continue here only if blen > 2. */ - - if (blen > 2) { - - tval = (old_val & ~(0xffff << (i * 8))) | - (SWAP16(interesting_16[j]) << (i * 8)); - - if (new_val == tval) return 1; - - } - - } - - } - - if (blen == 4 && check_le) { - - /* See if four-byte insertions could produce the same result - (LE only). */ - - for (j = 0; j < sizeof(interesting_32) / 4; j++) - if (new_val == (u32)interesting_32[j]) return 1; - - } - - return 0; - -} - - -/* Take the current entry from the queue, fuzz it for a while. This - function is a tad too long... returns 0 if fuzzed successfully, 1 if - skipped or bailed out. */ -//vector ir_set; - -static u8 fuzz_one(char** argv) { - - s32 len, fd, temp_len, i, j; - u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; - u64 havoc_queued, orig_hit_cnt, new_hit_cnt; - u32 splice_cycle = 0, perf_score = 100, orig_perf, prev_cksum, eff_cnt = 1; - u8 ret_val = 1, doing_det = 0; - - u8 a_collect[MAX_AUTO_EXTRA]; - u32 a_len = 0; - - int skip_count = 0; - -#ifdef IGNORE_FINDS - - /* In IGNORE_FINDS mode, skip any entries that weren't in the - initial data set. */ - - if (queue_cur->depth > 1) return 1; - -#else - - if (pending_favored) { - - /* If we have any favored, non-fuzzed new arrivals in the queue, - possibly skip to them at the expense of already-fuzzed or non-favored - cases. */ - - if ((queue_cur->was_fuzzed || !queue_cur->favored) && - UR(100) < SKIP_TO_NEW_PROB) return 1; - - } else if (!dumb_mode && !queue_cur->favored && queued_paths > 10) { - - /* Otherwise, still possibly skip non-favored cases, albeit less often. - The odds of skipping stuff are higher for already-fuzzed inputs and - lower for never-fuzzed entries. */ - - if (queue_cycle > 1 && !queue_cur->was_fuzzed) { - - if (UR(100) < SKIP_NFAV_NEW_PROB) return 1; - - } else { - - if (UR(100) < SKIP_NFAV_OLD_PROB) return 1; - - } - - } - -#endif /* ^IGNORE_FINDS */ - - if (not_on_tty) { - ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", - current_entry, queued_paths, unique_crashes); - fflush(stdout); - } - - /* Map the test case into memory. */ - - fd = open(queue_cur->fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", queue_cur->fname); - - len = queue_cur->len; - - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (orig_in == MAP_FAILED) PFATAL("Unable to mmap '%s'", queue_cur->fname); - - close(fd); - - out_buf = ck_alloc_nozero(len+1); - - subseq_tmouts = 0; - - cur_depth = queue_cur->depth; - - memcpy(out_buf, in_buf, len); - out_buf[len] = 0; - - orig_perf = perf_score = calculate_score(queue_cur); - - doing_det = 1; - - stage_short = "SQL fuzz"; - stage_max = len << 3; - stage_name = "fuzzing"; - - stage_val_type = STAGE_VAL_NONE; - - orig_hit_cnt = queued_paths + unique_crashes; - - prev_cksum = queue_cur->exec_cksum; - - seed_count++; - - //********************** - - vector mutated_tree = g_mutator.mutate_all((const char*)out_buf); - - stage_max = mutated_tree.size(); - stage_cur = 0; - - for(InputInfo* input: mutated_tree){ - stage_name = "sql_validate"; - - u8* fn = alloc_printf("%s/crash_input", out_dir); - s32 fd; - FILE* f; - - fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_free(fn); - - f = fdopen(fd, "w"); - - if (!f) PFATAL("fdopen() failed"); - - fprintf(f, "%s\n", input->input_->to_string().c_str()); - - fclose(f); - - bool tmp_res = g_instantiator.instantaite_sql(input->input_); - - if( tmp_res == false){ - skip_count ++ ; - continue; - } - show_stats(); - string ir_str = input->input_->to_string(); - g_current_input = input; - - char* tmp_str = ir_str.c_str(); - int siz = ir_str.size(); - - stage_name = "sql_fuzz"; - if(common_fuzz_stuff(argv, tmp_str, siz)){ - goto abandon_entry; - } - stage_cur++; - show_stats(); - } - - //********************** - - stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; - stage_cycles[STAGE_FLIP1] += mutated_tree.size() - skip_count; - - - new_hit_cnt = queued_paths + unique_crashes; - - ret_val = 0; - -abandon_entry: - for(InputInfo* input: mutated_tree){ - delete input; - } - - - splicing_with = -1; - - /* Update pending_not_fuzzed count if we made it through the calibration - cycle and have not seen this entry before. */ - - if (!stop_soon && !queue_cur->cal_failed && !queue_cur->was_fuzzed) { - queue_cur->was_fuzzed = 1; - pending_not_fuzzed--; - if (queue_cur->favored) pending_favored--; - } - - munmap(orig_in, queue_cur->len); - - - if (in_buf != orig_in){ ck_free(in_buf);} - - ck_free(out_buf); - ck_free(eff_map); - //ir_set.clear(); - - return ret_val; -} - - -/* Grab interesting test cases from other fuzzers. */ - -static void sync_fuzzers(char** argv) { - - DIR* sd; - struct dirent* sd_ent; - u32 sync_cnt = 0; - - sd = opendir(sync_dir); - if (!sd) PFATAL("Unable to open '%s'", sync_dir); - - stage_max = stage_cur = 0; - cur_depth = 0; - - /* Look at the entries created for every other fuzzer in the sync directory. */ - - while ((sd_ent = readdir(sd))) { - - static u8 stage_tmp[128]; - - DIR* qd; - struct dirent* qd_ent; - u8 *qd_path, *qd_synced_path; - u32 min_accept = 0, next_min_accept; - - s32 id_fd; - - /* Skip dot files and our own output directory. */ - - if (sd_ent->d_name[0] == '.' || !strcmp(sync_id, sd_ent->d_name)) continue; - - /* Skip anything that doesn't have a queue/ subdirectory. */ - - qd_path = alloc_printf("%s/%s/queue", sync_dir, sd_ent->d_name); - - if (!(qd = opendir(qd_path))) { - ck_free(qd_path); - continue; - } - - /* Retrieve the ID of the last seen test case. */ - - qd_synced_path = alloc_printf("%s/.synced/%s", out_dir, sd_ent->d_name); - - id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); - - if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path); - - if (read(id_fd, &min_accept, sizeof(u32)) > 0) - lseek(id_fd, 0, SEEK_SET); - - next_min_accept = min_accept; - - /* Show stats */ - - sprintf(stage_tmp, "sync %u", ++sync_cnt); - stage_name = stage_tmp; - stage_cur = 0; - stage_max = 0; - - /* For every file queued by this fuzzer, parse ID and see if we have looked at - it before; exec a test case if not. */ - - while ((qd_ent = readdir(qd))) { - - u8* path; - s32 fd; - struct stat st; - - if (qd_ent->d_name[0] == '.' || - sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &syncing_case) != 1 || - syncing_case < min_accept) continue; - - /* OK, sounds like a new one. Let's give it a try. */ - - if (syncing_case >= next_min_accept) - next_min_accept = syncing_case + 1; - - path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); - - /* Allow this to fail in case the other fuzzer is resuming or so... */ - - fd = open(path, O_RDONLY); - - if (fd < 0) { - ck_free(path); - continue; - } - - if (fstat(fd, &st)) PFATAL("fstat() failed"); - - /* Ignore zero-sized or oversized files. */ - - if (st.st_size && st.st_size <= MAX_FILE) { - - u8 fault; - u8* mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - - if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path); - - /* See what happens. We rely on save_if_interesting() to catch major - errors and save the test case. */ - - write_to_testcase(mem, st.st_size); - - fault = run_target(argv, exec_tmout); - - if (stop_soon) return; - - syncing_party = sd_ent->d_name; - queued_imported += save_if_interesting(argv, mem, st.st_size, fault); - syncing_party = 0; - - munmap(mem, st.st_size); - - if (!(stage_cur++ % stats_update_freq)) show_stats(); - - } - - ck_free(path); - close(fd); - - } - - ck_write(id_fd, &next_min_accept, sizeof(u32), qd_synced_path); - - close(id_fd); - closedir(qd); - ck_free(qd_path); - ck_free(qd_synced_path); - - } - - closedir(sd); - -} - - -/* Handle stop signal (Ctrl-C, etc). */ - -static void handle_stop_sig(int sig) { - - stop_soon = 1; - - if (child_pid > 0) kill(child_pid, SIGKILL); - if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); - -} - - -/* Handle skip request (SIGUSR1). */ - -static void handle_skipreq(int sig) { - - skip_requested = 1; - -} - -/* Handle timeout (SIGALRM). */ - -static void handle_timeout(int sig) { - - if (child_pid > 0) { - - child_timed_out = 1; - kill(child_pid, SIGKILL); - - } else if (child_pid == -1 && forksrv_pid > 0) { - - child_timed_out = 1; - kill(forksrv_pid, SIGKILL); - - } - -} - - -/* Do a PATH search and find target binary to see that it exists and - isn't a shell script - a common and painful mistake. We also check for - a valid ELF header and for evidence of AFL instrumentation. */ - -EXP_ST void check_binary(u8* fname) { - - u8* env_path = 0; - struct stat st; - - s32 fd; - u8* f_data; - u32 f_len = 0; - - ACTF("Validating target binary..."); - - if (strchr((char *)fname, '/') || !(env_path = getenv("PATH"))) { - - target_path = ck_strdup(fname); - if (stat(target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || (f_len = st.st_size) < 4) - FATAL("Program '%s' not found or not executable", fname); - - } else { - - while (env_path) { - - u8 *cur_elem, *delim = strchr((char *)env_path, ':'); - - if (delim) { - - cur_elem = ck_alloc(delim - env_path + 1); - memcpy(cur_elem, env_path, delim - env_path); - delim++; - - } else cur_elem = ck_strdup(env_path); - - env_path = delim; - - if (cur_elem[0]) - target_path = alloc_printf("%s/%s", cur_elem, fname); - else - target_path = ck_strdup(fname); - - ck_free(cur_elem); - - if (!stat(target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && (f_len = st.st_size) >= 4) break; - - ck_free(target_path); - target_path = 0; - - } - - if (!target_path) FATAL("Program '%s' not found or not executable", fname); - - } - - if (getenv("AFL_SKIP_BIN_CHECK")) return; - - /* Check for blatant user errors. */ - - if ((!strncmp(target_path, "/tmp/", 5) && !strchr((char *)target_path + 5, '/')) || - (!strncmp(target_path, "/var/tmp/", 9) && !strchr((char *)target_path + 9, '/'))) - FATAL("Please don't keep binaries in /tmp or /var/tmp"); - - fd = open(target_path, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", target_path); - - f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); - - if (f_data == MAP_FAILED) PFATAL("Unable to mmap file '%s'", target_path); - - close(fd); - - if (f_data[0] == '#' && f_data[1] == '!') { - - SAYF("\n" cLRD "[-] " cRST - "Oops, the target binary looks like a shell script. Some build systems will\n" - " sometimes generate shell stubs for dynamically linked programs; try static\n" - " library mode (./configure --disable-shared) if that's the case.\n\n" - - " Another possible cause is that you are actually trying to use a shell\n" - " wrapper around the fuzzed component. Invoking shell can slow down the\n" - " fuzzing process by a factor of 20x or more; it's best to write the wrapper\n" - " in a compiled language instead.\n"); - - FATAL("Program '%s' is a shell script", target_path); - - } - -#ifndef __APPLE__ - - if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) - FATAL("Program '%s' is not an ELF binary", target_path); - -#else - - if (f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) - FATAL("Program '%s' is not a 64-bit Mach-O binary", target_path); - -#endif /* ^!__APPLE__ */ - - if (!qemu_mode && !dumb_mode && - !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { - - SAYF("\n" cLRD "[-] " cRST - "Looks like the target binary is not instrumented! The fuzzer depends on\n" - " compile-time instrumentation to isolate interesting test cases while\n" - " mutating the input data. For more information, and for tips on how to\n" - " instrument binaries, please see %s/README.\n\n" - - " When source code is not available, you may be able to leverage QEMU\n" - " mode support. Consult the README for tips on how to enable this.\n" - - " (It is also possible to use afl-fuzz as a traditional, \"dumb\" fuzzer.\n" - " For that, you can use the -n option - but expect much worse results.)\n", - doc_path); - - FATAL("No instrumentation detected"); - - } - - if (qemu_mode && - memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { - - SAYF("\n" cLRD "[-] " cRST - "This program appears to be instrumented with afl-gcc, but is being run in\n" - " QEMU mode (-Q). This is probably not what you want - this setup will be\n" - " slow and offer no practical benefits.\n"); - - FATAL("Instrumentation found in -Q mode"); - - } - - if (memmem(f_data, f_len, "libasan.so", 10) || - memmem(f_data, f_len, "__msan_init", 11)) uses_asan = 1; - - /* Detect persistent & deferred init signatures in the binary. */ - - if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { - - OKF(cPIN "Persistent mode binary detected."); - setenv(PERSIST_ENV_VAR, "1", 1); - persistent_mode = 1; - - } else if (getenv("AFL_PERSISTENT")) { - - WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); - - } - - if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { - - OKF(cPIN "Deferred forkserver binary detected."); - setenv(DEFER_ENV_VAR, "1", 1); - deferred_mode = 1; - - } else if (getenv("AFL_DEFER_FORKSRV")) { - - WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); - - } - - if (munmap(f_data, f_len)) PFATAL("unmap() failed"); - -} - - -/* Trim and possibly create a banner for the run. */ - -static void fix_up_banner(u8* name) { - - if (!use_banner) { - - if (sync_id) { - - use_banner = sync_id; - - } else { - - u8* trim = strrchr((const char*)name, '/'); - if (!trim) use_banner = name; else use_banner = trim + 1; - - } - - } - - if (strlen(use_banner) > 40) { - - u8* tmp = ck_alloc(44); - sprintf(tmp, "%.40s...", use_banner); - use_banner = tmp; - - } - -} - - -/* Check if we're on TTY. */ - -static void check_if_tty(void) { - - struct winsize ws; - - if (getenv("AFL_NO_UI")) { - OKF("Disabling the UI because AFL_NO_UI is set."); - not_on_tty = 1; - return; - } - - if (ioctl(1, TIOCGWINSZ, &ws)) { - - if (errno == ENOTTY) { - OKF("Looks like we're not running on a tty, so I'll be a bit less verbose."); - not_on_tty = 1; - } - - return; - } - -} - - -/* Check terminal dimensions after resize. */ - -static void check_term_size(void) { - - struct winsize ws; - - term_too_small = 0; - - if (ioctl(1, TIOCGWINSZ, &ws)) return; - - if (ws.ws_row < 25 || ws.ws_col < 80) term_too_small = 1; - -} - - - -/* Display usage hints. */ - -static void usage(u8* argv0) { - - SAYF("\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n" - - "Required parameters:\n\n" - - " -i dir - input directory with test cases\n" - " -o dir - output directory for fuzzer findings\n\n" - - "Execution control settings:\n\n" - - " -f file - location read by the fuzzed program (stdin)\n" - " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" - " -m megs - memory limit for child process (%u MB)\n" - " -Q - use binary-only instrumentation (QEMU mode)\n\n" - - "Fuzzing behavior settings:\n\n" - - " -d - quick & dirty mode (skips deterministic steps)\n" - " -n - fuzz without instrumentation (dumb mode)\n" - " -x dir - optional fuzzer dictionary (see README)\n\n" - - "Other stuff:\n\n" - - " -T text - text banner to show on the screen\n" - " -M / -S id - distributed mode (see parallel_fuzzing.txt)\n" - " -C - crash exploration mode (the peruvian rabbit thing)\n\n" - - "For additional tips, please consult %s/README.\n\n", - - argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); - - exit(1); - -} - - -/* Prepare output directories and fds. */ - -EXP_ST void setup_dirs_fds(void) { - - u8* tmp; - s32 fd; - - ACTF("Setting up output directories..."); - - if (sync_id && mkdir(sync_dir, 0700) && errno != EEXIST) - PFATAL("Unable to create '%s'", sync_dir); - - if (mkdir(out_dir, 0700)) { - - if (errno != EEXIST) PFATAL("Unable to create '%s'", out_dir); - - maybe_delete_out_dir(); - - } else { - - if (in_place_resume) - FATAL("Resume attempted but old output directory not found"); - - out_dir_fd = open(out_dir, O_RDONLY); - -#ifndef __sun - - if (out_dir_fd < 0 || flock(out_dir_fd, LOCK_EX | LOCK_NB)) - PFATAL("Unable to flock() output directory."); - -#endif /* !__sun */ - - } - - /* Queue directory for any starting & discovered paths. */ - - tmp = alloc_printf("%s/queue", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Top-level directory for queue metadata used for session - resume and related tasks. */ - - tmp = alloc_printf("%s/queue/.state/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Directory for flagging queue entries that went through - deterministic fuzzing in the past. */ - - tmp = alloc_printf("%s/queue/.state/deterministic_done/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Directory with the auto-selected dictionary entries. */ - - tmp = alloc_printf("%s/queue/.state/auto_extras/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* The set of paths currently deemed redundant. */ - - tmp = alloc_printf("%s/queue/.state/redundant_edges/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* The set of paths showing variable behavior. */ - - tmp = alloc_printf("%s/queue/.state/variable_behavior/", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Sync directory for keeping track of cooperating fuzzers. */ - - if (sync_id) { - - tmp = alloc_printf("%s/.synced/", out_dir); - - if (mkdir(tmp, 0700) && (!in_place_resume || errno != EEXIST)) - PFATAL("Unable to create '%s'", tmp); - - ck_free(tmp); - - } - - /* All recorded crashes. */ - - tmp = alloc_printf("%s/crashes", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* All recorded hangs. */ - - tmp = alloc_printf("%s/hangs", out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - /* Generally useful file descriptors. */ - - dev_null_fd = open("/dev/null", O_RDWR); - if (dev_null_fd < 0) PFATAL("Unable to open /dev/null"); - - dev_urandom_fd = open("/dev/urandom", O_RDONLY); - if (dev_urandom_fd < 0) PFATAL("Unable to open /dev/urandom"); - - /* Gnuplot output file. */ - - tmp = alloc_printf("%s/plot_data", out_dir); - fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", tmp); - ck_free(tmp); - - plot_file = fdopen(fd, "w"); - if (!plot_file) PFATAL("fdopen() failed"); - - fprintf(plot_file, "# unix_time, cycles_done, cur_path, paths_total, " - "pending_total, pending_favs, map_size, unique_crashes, " - "unique_hangs, max_depth, execs_per_sec, total_execs, total_vaild, seed_count\n"); -} - - -/* Setup the output file for fuzzed data, if not using -f. */ - -EXP_ST void setup_stdio_file(void) { - - u8* fn = alloc_printf("%s/.cur_input", out_dir); - - unlink(fn); /* Ignore errors */ - - out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600); - - if (out_fd < 0) PFATAL("Unable to create '%s'", fn); - - ck_free(fn); - -} - - -/* Make sure that core dumps don't go to a program. */ - -static void check_crash_handling(void) { - -#ifdef __APPLE__ - - /* Yuck! There appears to be no simple C API to query for the state of - loaded daemons on MacOS X, and I'm a bit hesitant to do something - more sophisticated, such as disabling crash reporting via Mach ports, - until I get a box to test the code. So, for now, we check for crash - reporting the awful way. */ - - if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return; - - SAYF("\n" cLRD "[-] " cRST - "Whoops, your system is configured to forward crash notifications to an\n" - " external crash reporting utility. This will cause issues due to the\n" - " extended delay between the fuzzed binary malfunctioning and this fact\n" - " being relayed to the fuzzer via the standard waitpid() API.\n\n" - " To avoid having crashes misinterpreted as timeouts, please run the\n" - " following commands:\n\n" - - " SL=/System/Library; PL=com.apple.ReportCrash\n" - " launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n" - " sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n"); - - if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) - FATAL("Crash reporter detected"); - -#else - - /* This is Linux specific, but I don't think there's anything equivalent on - *BSD, so we can just let it slide for now. */ - - s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY); - u8 fchar; - - if (fd < 0) return; - - ACTF("Checking core_pattern..."); - - /*if (read(fd, &fchar, 1) == 1 && fchar == '|') { - - SAYF("\n" cLRD "[-] " cRST - "Hmm, your system is configured to send core dump notifications to an\n" - " external utility. This will cause issues: there will be an extended delay\n" - " between stumbling upon a crash and having this information relayed to the\n" - " fuzzer via the standard waitpid() API.\n\n" - - " To avoid having crashes misinterpreted as timeouts, please log in as root\n" - " and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" - - " echo core >/proc/sys/kernel/core_pattern\n"); - - if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) - FATAL("Pipe at the beginning of 'core_pattern'"); - - }*/ - - close(fd); - -#endif /* ^__APPLE__ */ - -} - - -/* Check CPU governor. */ - -static void check_cpu_governor(void) { - - FILE* f; - u8 tmp[128]; - u64 min = 0, max = 0; - - if (getenv("AFL_SKIP_CPUFREQ")) return; - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r"); - if (!f) return; - - ACTF("Checking CPU scaling governor..."); - - if (!fgets(tmp, 128, f)) PFATAL("fgets() failed"); - - fclose(f); - - if (!strncmp(tmp, "perf", 4)) return; - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r"); - - if (f) { - if (fscanf(f, "%llu", &min) != 1) min = 0; - fclose(f); - } - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r"); - - if (f) { - if (fscanf(f, "%llu", &max) != 1) max = 0; - fclose(f); - } - - if (min == max) return; - - SAYF("\n" cLRD "[-] " cRST - "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" - " between %llu and %llu MHz. Unfortunately, the scaling algorithm in the\n" - " kernel is imperfect and can miss the short-lived processes spawned by\n" - " afl-fuzz. To keep things moving, run these commands as root:\n\n" - - " cd /sys/devices/system/cpu\n" - " echo performance | tee cpu*/cpufreq/scaling_governor\n\n" - - " You can later go back to the original state by replacing 'performance' with\n" - " 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ\n" - " to make afl-fuzz skip this check - but expect some performance drop.\n", - min / 1024, max / 1024); - - FATAL("Suboptimal CPU scaling governor"); - -} - - -/* Count the number of logical CPU cores. */ - -static void get_core_count(void) { - - u32 cur_runnable = 0; - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) - - size_t s = sizeof(cpu_core_count); - - /* On *BSD systems, we can just use a sysctl to get the number of CPUs. */ - -#ifdef __APPLE__ - - if (sysctlbyname("hw.logicalcpu", &cpu_core_count, &s, NULL, 0) < 0) - return; - -#else - - int s_name[2] = { CTL_HW, HW_NCPU }; - - if (sysctl(s_name, 2, &cpu_core_count, &s, NULL, 0) < 0) return; - -#endif /* ^__APPLE__ */ - -#else - -#ifdef HAVE_AFFINITY - - cpu_core_count = sysconf(_SC_NPROCESSORS_ONLN); - -#else - - FILE* f = fopen("/proc/stat", "r"); - u8 tmp[1024]; - - if (!f) return; - - while (fgets(tmp, sizeof(tmp), f)) - if (!strncmp(tmp, "cpu", 3) && isdigit(tmp[3])) cpu_core_count++; - - fclose(f); - -#endif /* ^HAVE_AFFINITY */ - -#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ - - if (cpu_core_count > 0) { - - cur_runnable = (u32)get_runnable_processes(); - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) - - /* Add ourselves, since the 1-minute average doesn't include that yet. */ - - cur_runnable++; - -#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ - - OKF("You have %u CPU core%s and %u runnable tasks (utilization: %0.0f%%).", - cpu_core_count, cpu_core_count > 1 ? "s" : "", - cur_runnable, cur_runnable * 100.0 / cpu_core_count); - - if (cpu_core_count > 1) { - - if (cur_runnable > cpu_core_count * 1.5) { - - WARNF("System under apparent load, performance may be spotty."); - - } else if (cur_runnable + 1 <= cpu_core_count) { - - OKF("Try parallel jobs - see %s/parallel_fuzzing.txt.", doc_path); - - } - - } - - } else { - - cpu_core_count = 0; - WARNF("Unable to figure out the number of CPU cores."); - - } - -} - - -/* Validate and fix up out_dir and sync_dir when using -S. */ - -static void fix_up_sync(void) { - - u8* x = sync_id; - - if (dumb_mode) - FATAL("-S / -M and -n are mutually exclusive"); - - if (skip_deterministic) { - - if (force_deterministic) - FATAL("use -S instead of -M -d"); - else - FATAL("-S already implies -d"); - - } - - while (*x) { - - if (!isalnum(*x) && *x != '_' && *x != '-') - FATAL("Non-alphanumeric fuzzer ID specified via -S or -M"); - - x++; - - } - - if (strlen(sync_id) > 32) FATAL("Fuzzer ID too long"); - - x = alloc_printf("%s/%s", out_dir, sync_id); - - sync_dir = out_dir; - out_dir = x; - - if (!force_deterministic) { - skip_deterministic = 1; - use_splicing = 1; - } - -} - - -/* Handle screen resize (SIGWINCH). */ - -static void handle_resize(int sig) { - clear_screen = 1; -} - - -/* Check ASAN options. */ - -static void check_asan_opts(void) { - u8* x = getenv("ASAN_OPTIONS"); - - if (x) { - - if (!strstr((char *)x, "abort_on_error=1")) - FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - - if (!strstr((char *)x, "symbolize=0")) - FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); - - } - - x = getenv("MSAN_OPTIONS"); - - if (x) { - - if (!strstr((char *)x, "exit_code=" STRINGIFY(MSAN_ERROR))) - FATAL("Custom MSAN_OPTIONS set without exit_code=" - STRINGIFY(MSAN_ERROR) " - please fix!"); - - if (!strstr((char *)x, "symbolize=0")) - FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); - - } - -} - - -/* Detect @@ in args. */ - -EXP_ST void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr((const char*)argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - /* If we don't have a file name chosen yet, use a safe default. */ - - if (!out_file) - out_file = alloc_printf("%s/.cur_input", out_dir); - - /* Be sure that we're always using fully-qualified paths. */ - - if (out_file[0] == '/') aa_subst = out_file; - else aa_subst = alloc_printf("%s/%s", cwd, out_file); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (out_file[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - -/* Set up signal handlers. More complicated that needs to be, because libc on - Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call - siginterrupt(), and does other unnecessary things. */ - -EXP_ST void setup_signal_handlers(void) { - - struct sigaction sa; - - sa.sa_handler = NULL; - sa.sa_flags = SA_RESTART; - sa.sa_sigaction = NULL; - - sigemptyset(&sa.sa_mask); - - /* Various ways of saying "stop". */ - - sa.sa_handler = handle_stop_sig; - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - - /* Exec timeout notifications. */ - - sa.sa_handler = handle_timeout; - sigaction(SIGALRM, &sa, NULL); - - /* Window resize */ - - sa.sa_handler = handle_resize; - sigaction(SIGWINCH, &sa, NULL); - - /* SIGUSR1: skip entry */ - - sa.sa_handler = handle_skipreq; - sigaction(SIGUSR1, &sa, NULL); - - /* Things we don't care about. */ - - sa.sa_handler = SIG_IGN; - sigaction(SIGTSTP, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - -} - - -/* Rewrite argv for QEMU. */ - -static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 *tmp, *cp, *rsl, *own_copy; - - /* Workaround for a QEMU stability glitch. */ - - setenv("QEMU_LOG", "nochain", 1); - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - new_argv[2] = target_path; - new_argv[1] = "--"; - - /* Now we need to actually find the QEMU binary to put in argv[0]. */ - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) - FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr((const char*)own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); - return new_argv; - - } - - SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be built\n" - " separately by following the instructions in qemu_mode/README.qemu. If you\n" - " already have the binary installed, you may need to specify AFL_PATH in the\n" - " environment.\n\n" - - " Of course, even without QEMU, afl-fuzz can still work with binaries that are\n" - " instrumented at compile time with afl-gcc. It is also possible to use it as a\n" - " traditional \"dumb\" fuzzer by specifying '-n' in the command line.\n"); - - FATAL("Failed to locate 'afl-qemu-trace'."); - -} - - -/* Make a copy of the current command line. */ - -static void save_cmdline(u32 argc, char** argv) { - - u32 len = 1, i; - u8* buf; - - for (i = 0; i < argc; i++) - len += strlen(argv[i]) + 1; - - buf = orig_cmdline = ck_alloc(len); - - for (i = 0; i < argc; i++) { - - u32 l = strlen(argv[i]); - - memcpy(buf, argv[i], l); - buf += l; - - if (i != argc - 1) *(buf++) = ' '; - - } - - *buf = 0; - -} - -#ifndef AFL_LIB - -char* g_server_path; -char* g_client_path; - -int main(int argc, char** argv) { - s32 opt; - u64 prev_queued = 0; - u32 sync_interval_cnt = 0, seek_to; - u8 *extras_dir = 0; - u8 mem_limit_given = 0; - u8 exit_1 = !!getenv("AFL_BENCH_JUST_ONE"); - char** use_argv; - - struct timeval tv; - struct timezone tz; - memset_fucking_array(); - SAYF(cCYA "SQLFuzzer " cBRI VERSION cRST " by hackers\n");//string_lib he common_string_lib YOUSHENME QUBIE - - doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - - gettimeofday(&tv, &tz); - srandom(tv.tv_sec ^ tv.tv_usec ^ getpid()); - - while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q:s:c:")) > 0) - - switch (opt) { - case 'i': /* input dir */ - - if (in_dir) FATAL("Multiple -i options not supported"); - in_dir = optarg; - - if (!strcmp(in_dir, "-")) in_place_resume = 1; - - break; - - case 's': /* server's path */ - if (g_server_path) FATAL("Multiple -s options not supported"); - g_server_path = optarg; - break; - - case 'o': /* output dir */ - - if (out_dir) FATAL("Multiple -o options not supported"); - out_dir = optarg; - break; - - case 'M': { /* master sync ID */ - - u8* c; - - if (sync_id) FATAL("Multiple -S or -M options not supported"); - sync_id = ck_strdup(optarg); - - if ((c = strchr((char *)sync_id, ':'))) { - - *c = 0; - - if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 || - !master_id || !master_max || master_id > master_max || - master_max > 1000000) FATAL("Bogus master ID passed to -M"); - - } - - force_deterministic = 1; - - } - - break; - - case 'S': - - if (sync_id) FATAL("Multiple -S or -M options not supported"); - sync_id = ck_strdup(optarg); - break; - - case 'f': /* target file */ - - if (out_file) FATAL("Multiple -f options not supported"); - out_file = optarg; - break; - - case 'x': /* dictionary */ - - if (extras_dir) FATAL("Multiple -x options not supported"); - extras_dir = optarg; - break; - - case 't': { /* timeout */ - - u8 suffix = 0; - - if (timeout_given) FATAL("Multiple -t options not supported"); - - if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 || - optarg[0] == '-') FATAL("Bad syntax used for -t"); - - if (exec_tmout < 5) FATAL("Dangerously low value of -t"); - - if (suffix == '+') timeout_given = 2; else timeout_given = 1; - - break; - - } - - case 'm': { /* mem limit */ - - u8 suffix = 'M'; - - if (mem_limit_given) FATAL("Multiple -m options not supported"); - mem_limit_given = 1; - - if (!strcmp(optarg, "none")) { - - mem_limit = 0; - break; - - } - - if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || - optarg[0] == '-') FATAL("Bad syntax used for -m"); - - switch (suffix) { - - case 'T': mem_limit *= 1024 * 1024; break; - case 'G': mem_limit *= 1024; break; - case 'k': mem_limit /= 1024; break; - case 'M': break; - - default: FATAL("Unsupported suffix or bad syntax for -m"); - - } - - if (mem_limit < 5) FATAL("Dangerously low value of -m"); - - if (sizeof(rlim_t) == 4 && mem_limit > 2000) - FATAL("Value of -m out of range on 32-bit systems"); - - } - - break; - - case 'd': /* skip deterministic */ - - if (skip_deterministic) FATAL("Multiple -d options not supported"); - skip_deterministic = 1; - use_splicing = 1; - break; - - case 'B': /* load bitmap */ - - /* This is a secret undocumented option! It is useful if you find - an interesting test case during a normal fuzzing process, and want - to mutate it without rediscovering any of the test cases already - found during an earlier run. - - To use this mode, you need to point -B to the fuzz_bitmap produced - by an earlier run for the exact same binary... and that's it. - - I only used this once or twice to get variants of a particular - file, so I'm not making this an official setting. */ - - if (in_bitmap) FATAL("Multiple -B options not supported"); - - in_bitmap = optarg; - read_bitmap(in_bitmap); - break; - - case 'C': /* crash mode */ - - if (crash_mode) FATAL("Multiple -C options not supported"); - crash_mode = FAULT_CRASH; - break; - - case 'n': /* dumb mode */ - - if (dumb_mode) FATAL("Multiple -n options not supported"); - if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1; - - break; - - case 'T': /* banner */ - - if (use_banner) FATAL("Multiple -T options not supported"); - use_banner = optarg; - break; - - case 'Q': /* QEMU mode */ - - if (qemu_mode) FATAL("Multiple -Q options not supported"); - qemu_mode = 1; - - if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; - - break; - - default: - - usage(argv[0]); - - } - - if (optind == argc || !in_dir || !out_dir) usage(argv[0]); - - setup_signal_handlers(); - check_asan_opts(); - - if (sync_id) fix_up_sync(); - - if (!strcmp(in_dir, out_dir)) - FATAL("Input and output directories can't be the same"); - - if (dumb_mode) { - - if (crash_mode) FATAL("-C and -n are mutually exclusive"); - if (qemu_mode) FATAL("-Q and -n are mutually exclusive"); - - } - - no_forkserver = 1; - if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1; - if (getenv("AFL_NO_ARITH")) no_arith = 1; - if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1; - if (getenv("AFL_FAST_CAL")) fast_cal = 1; - - if (getenv("AFL_HANG_TMOUT")) { - hang_tmout = atoi(getenv("AFL_HANG_TMOUT")); - if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); - } - - if (dumb_mode == 2 && no_forkserver) - FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); - - if (getenv("AFL_PRELOAD")) { - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); - } - - if (getenv("AFL_LD_PRELOAD")) - FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); - - save_cmdline(argc, argv); - - fix_up_banner(argv[optind]); - - check_if_tty(); - - get_core_count(); - - #ifdef HAVE_AFFINITY - bind_to_free_cpu(); - #endif /* HAVE_AFFINITY */ - //check_crash_handling(); - check_cpu_governor(); - - setup_post(); - setup_shm(); - init_count_class16(); - - setup_dirs_fds(); - read_testcases(); - load_auto(); - - pivot_inputs(); - - if (extras_dir) load_extras(extras_dir); - - if (!timeout_given) find_timeout(); - - detect_file_args(argv + optind + 1); - - if (!out_file) setup_stdio_file(); - - //check_binary(argv[optind]); - //check_binary(g_server_path); - - start_time = get_cur_time(); - last_save_time = start_time; - - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else - use_argv = argv + optind; - - g_mutator.init_IR_library(INIT_LIB); - g_mutator.init_IR_config_info(GRAMMAR_INFORMATION); - - g_connector.close_db(); - g_connector.start_db(file, options); - - //char* tmp_argv[] = {g_server_path, NULL}; - //init_forkserver(tmp_argv); - // to do - perform_dry_run(use_argv); - - cull_queue(); - - show_init_stats(); - - seek_to = find_start_position(); - - write_stats_file(0, 0, 0); - save_auto(); - - if (stop_soon) goto stop_fuzzing; - - /* Woop woop woop */ - - if (!not_on_tty) { - sleep(4); - start_time += 4000; - if (stop_soon) goto stop_fuzzing; - } - - //reboot_server(0x1000000);//start server before we fuzz - while (1) { - - u8 skipped_fuzz; - - cull_queue(); - - if (!queue_cur) { - - queue_cycle++; - current_entry = 0; - cur_skipped_paths = 0; - queue_cur = queue; - - while (seek_to) { - current_entry++; - seek_to--; - queue_cur = queue_cur->next; - } - - show_stats(); - - if (not_on_tty) { - ACTF("Entering queue cycle %llu.", queue_cycle); - fflush(stdout); - } - - /* If we had a full queue cycle with no new finds, try - recombination strategies next. */ - - if (queued_paths == prev_queued) { - - if (use_splicing) cycles_wo_finds++; else use_splicing = 1; - - } else cycles_wo_finds = 0; - - prev_queued = queued_paths; - - if (sync_id && queue_cycle == 1 && getenv("AFL_IMPORT_FIRST")) - sync_fuzzers(use_argv); - - } - - skipped_fuzz = fuzz_one(use_argv); - - if (!stop_soon && sync_id && !skipped_fuzz) { - - if (!(sync_interval_cnt++ % SYNC_INTERVAL)) - sync_fuzzers(use_argv); - - } - - if (!stop_soon && exit_1) stop_soon = 2; - - if (stop_soon) break; - - queue_cur = queue_cur->next; - current_entry++; - } - - if (queue_cur) show_stats(); - - write_bitmap(); - write_stats_file(0, 0, 0); - save_auto(); - -stop_fuzzing: - - SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, - stop_soon == 2 ? "programmatically" : "by user"); - - /* Running for more than 30 minutes but still doing first cycle? */ - - if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) { - - SAYF("\n" cYEL "[!] " cRST - "Stopped during the first cycle, results may be incomplete.\n" - " (For info on resuming, see %s/README.)\n", doc_path); - - } - - //g_mutator.print_information(OUTPUT_PATH); - g_connector.close_db(); - - fclose(plot_file); - destroy_queue(); - destroy_extras(); - ck_free(target_path); - ck_free(sync_id); - - alloc_report(); - - OKF("We're done here. Have a nice day!\n"); - - exit(0); - -} - -#endif /* !AFL_LIB */ diff --git a/AFL/alloc-inl.h b/AFL/alloc-inl.h deleted file mode 100755 index 9a68126..0000000 --- a/AFL/alloc-inl.h +++ /dev/null @@ -1,577 +0,0 @@ -/* - Copyright 2013 Google LLC All rights reserved. - - 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. -*/ - -/* - american fuzzy lop - error-checking, memory-zeroing alloc routines - ------------------------------------------------------------------ - - Written and maintained by Michal Zalewski - - This allocator is not designed to resist malicious attackers (the canaries - are small and predictable), but provides a robust and portable way to detect - use-after-free, off-by-one writes, stale pointers, and so on. -*/ - -#ifndef _HAVE_ALLOC_INL_H -#define _HAVE_ALLOC_INL_H - -#include -#include -#include - -#include "config.h" -#include "types.h" -#include "debug.h" - -/* User-facing macro to sprintf() to a dynamically allocated buffer. */ - -#define alloc_printf(_str...) ({ \ - u8* _tmp; \ - s32 _len = snprintf(NULL, 0, _str); \ - if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \ - _tmp = ck_alloc(_len + 1); \ - snprintf((char*)_tmp, _len + 1, _str); \ - _tmp; \ - }) - -/* Macro to enforce allocation limits as a last-resort defense against - integer overflows. */ - -#define ALLOC_CHECK_SIZE(_s) do { \ - if ((_s) > MAX_ALLOC) \ - ABORT("Bad alloc request: %u bytes", (_s)); \ - } while (0) - -/* Macro to check malloc() failures and the like. */ - -#define ALLOC_CHECK_RESULT(_r, _s) do { \ - if (!(_r)) \ - ABORT("Out of memory: can't allocate %u bytes", (_s)); \ - } while (0) - -/* Magic tokens used to mark used / freed chunks. */ - -#define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ -#define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ -#define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */ - -/* Positions of guard tokens in relation to the user-visible pointer. */ - -#define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) -#define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) -#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) - -#define ALLOC_OFF_HEAD 8 -#define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) - -/* Allocator increments for ck_realloc_block(). */ - -#define ALLOC_BLK_INC 256 - -/* Sanity-checking macros for pointers. */ - -#define CHECK_PTR(_p) do { \ - if (_p) { \ - if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ - if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ - ABORT("Use after free."); \ - else ABORT("Corrupted head alloc canary."); \ - } \ - if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ - ABORT("Corrupted tail alloc canary."); \ - } \ - } while (0) - -#define CHECK_PTR_EXPR(_p) ({ \ - typeof (_p) _tmp = (_p); \ - CHECK_PTR(_tmp); \ - _tmp; \ - }) - - -/* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized - requests. */ - -static inline void* DFL_ck_alloc_nozero(u32 size) { - - void* ret; - - if (!size) return NULL; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - return ret; - -} - - -/* Allocate a buffer, returning zeroed memory. */ - -static inline void* DFL_ck_alloc(u32 size) { - - void* mem; - - if (!size) return NULL; - mem = DFL_ck_alloc_nozero(size); - - return memset(mem, 0, size); - -} - - -/* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD - is set, the old memory will be also clobbered with 0xFF. */ - -static inline void DFL_ck_free(void* mem) { - - if (!mem) return; - - CHECK_PTR(mem); - -#ifdef DEBUG_BUILD - - /* Catch pointer issues sooner. */ - memset(mem, 0xFF, ALLOC_S(mem)); - -#endif /* DEBUG_BUILD */ - - ALLOC_C1(mem) = ALLOC_MAGIC_F; - - free(mem - ALLOC_OFF_HEAD); - -} - - -/* Re-allocate a buffer, checking for issues and zeroing any newly-added tail. - With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the - old memory is clobbered with 0xFF. */ - -static inline void* DFL_ck_realloc(void* orig, u32 size) { - - void* ret; - u32 old_size = 0; - - if (!size) { - - DFL_ck_free(orig); - return NULL; - - } - - if (orig) { - - CHECK_PTR(orig); - -#ifndef DEBUG_BUILD - ALLOC_C1(orig) = ALLOC_MAGIC_F; -#endif /* !DEBUG_BUILD */ - - old_size = ALLOC_S(orig); - orig -= ALLOC_OFF_HEAD; - - ALLOC_CHECK_SIZE(old_size); - - } - - ALLOC_CHECK_SIZE(size); - -#ifndef DEBUG_BUILD - - ret = realloc(orig, size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - -#else - - /* Catch pointer issues sooner: force relocation and make sure that the - original buffer is wiped. */ - - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - if (orig) { - - memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); - memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); - - ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; - - free(orig); - - } - -#endif /* ^!DEBUG_BUILD */ - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - if (size > old_size) - memset(ret + old_size, 0, size - old_size); - - return ret; - -} - - -/* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up - repeated small reallocs without complicating the user code). */ - -static inline void* DFL_ck_realloc_block(void* orig, u32 size) { - -#ifndef DEBUG_BUILD - - if (orig) { - - CHECK_PTR(orig); - - if (ALLOC_S(orig) >= size) return orig; - - size += ALLOC_BLK_INC; - - } - -#endif /* !DEBUG_BUILD */ - - return DFL_ck_realloc(orig, size); - -} - - -/* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */ - -static inline u8* DFL_ck_strdup(u8* str) { - - void* ret; - u32 size; - - if (!str) return NULL; - - size = strlen((char*)str) + 1; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - return memcpy(ret, str, size); - -} - - -/* Create a buffer with a copy of a memory block. Returns NULL for zero-sized - or NULL inputs. */ - -static inline void* DFL_ck_memdup(void* mem, u32 size) { - - void* ret; - - if (!mem || !size) return NULL; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - return memcpy(ret, mem, size); - -} - - -/* Create a buffer with a block of text, appending a NUL terminator at the end. - Returns NULL for zero-sized or NULL inputs. */ - -static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { - - u8* ret; - - if (!mem || !size) return NULL; - - ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL + 1); - ALLOC_CHECK_RESULT(ret, size); - - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; - - memcpy(ret, mem, size); - ret[size] = 0; - - return ret; - -} - - -#ifndef DEBUG_BUILD - -/* In non-debug mode, we just do straightforward aliasing of the above functions - to user-visible names such as ck_alloc(). */ - -#define ck_alloc DFL_ck_alloc -#define ck_alloc_nozero DFL_ck_alloc_nozero -#define ck_realloc DFL_ck_realloc -#define ck_realloc_block DFL_ck_realloc_block -#define ck_strdup DFL_ck_strdup -#define ck_memdup DFL_ck_memdup -#define ck_memdup_str DFL_ck_memdup_str -#define ck_free DFL_ck_free - -#define alloc_report() - -#else - -/* In debugging mode, we also track allocations to detect memory leaks, and the - flow goes through one more layer of indirection. */ - -/* Alloc tracking data structures: */ - -#define ALLOC_BUCKETS 4096 - -struct TRK_obj { - void *ptr; - char *file, *func; - u32 line; -}; - -#ifdef AFL_MAIN - -struct TRK_obj* TRK[ALLOC_BUCKETS]; -u32 TRK_cnt[ALLOC_BUCKETS]; - -# define alloc_report() TRK_report() - -#else - -extern struct TRK_obj* TRK[ALLOC_BUCKETS]; -extern u32 TRK_cnt[ALLOC_BUCKETS]; - -# define alloc_report() - -#endif /* ^AFL_MAIN */ - -/* Bucket-assigning function for a given pointer: */ - -#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) - - -/* Add a new entry to the list of allocated objects. */ - -static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, - u32 line) { - - u32 i, bucket; - - if (!ptr) return; - - bucket = TRKH(ptr); - - /* Find a free slot in the list of entries for that bucket. */ - - for (i = 0; i < TRK_cnt[bucket]; i++) - - if (!TRK[bucket][i].ptr) { - - TRK[bucket][i].ptr = ptr; - TRK[bucket][i].file = (char*)file; - TRK[bucket][i].func = (char*)func; - TRK[bucket][i].line = line; - return; - - } - - /* No space available - allocate more. */ - - TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], - (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); - - TRK[bucket][i].ptr = ptr; - TRK[bucket][i].file = (char*)file; - TRK[bucket][i].func = (char*)func; - TRK[bucket][i].line = line; - - TRK_cnt[bucket]++; - -} - - -/* Remove entry from the list of allocated objects. */ - -static inline void TRK_free_buf(void* ptr, const char* file, const char* func, - u32 line) { - - u32 i, bucket; - - if (!ptr) return; - - bucket = TRKH(ptr); - - /* Find the element on the list... */ - - for (i = 0; i < TRK_cnt[bucket]; i++) - - if (TRK[bucket][i].ptr == ptr) { - - TRK[bucket][i].ptr = 0; - return; - - } - - WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", - func, file, line); - -} - - -/* Do a final report on all non-deallocated objects. */ - -static inline void TRK_report(void) { - - u32 i, bucket; - - fflush(0); - - for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) - for (i = 0; i < TRK_cnt[bucket]; i++) - if (TRK[bucket][i].ptr) - WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", - TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); - -} - - -/* Simple wrappers for non-debugging functions: */ - -static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, - u32 line) { - - void* ret = DFL_ck_alloc(size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_realloc(orig, size); - TRK_free_buf(orig, file, func, line); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_realloc_block(orig, size); - TRK_free_buf(orig, file, func, line); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, - u32 line) { - - void* ret = DFL_ck_strdup(str); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_memdup(mem, size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_memdup_str(mem, size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - - -static inline void TRK_ck_free(void* ptr, const char* file, - const char* func, u32 line) { - - TRK_free_buf(ptr, file, func, line); - DFL_ck_free(ptr); - -} - -/* Aliasing user-facing names to tracking functions: */ - -#define ck_alloc(_p1) \ - TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_alloc_nozero(_p1) \ - TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_realloc(_p1, _p2) \ - TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_realloc_block(_p1, _p2) \ - TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_strdup(_p1) \ - TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_memdup(_p1, _p2) \ - TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_memdup_str(_p1, _p2) \ - TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_free(_p1) \ - TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) - -#endif /* ^!DEBUG_BUILD */ - -#endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/AFL/config.h b/AFL/config.h deleted file mode 100755 index 52fc352..0000000 --- a/AFL/config.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - Copyright 2013 Google LLC All rights reserved. - - 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. -*/ - -/* - american fuzzy lop - vaguely configurable bits - ---------------------------------------------- - - Written and maintained by Michal Zalewski -*/ - -#ifndef _HAVE_CONFIG_H -#define _HAVE_CONFIG_H - -#include "types.h" - -/* Version string: */ - -#define VERSION "2.56b" - -/****************************************************** - * * - * Settings that may be of interest to power users: * - * * - ******************************************************/ - -/* Comment out to disable terminal colors (note that this makes afl-analyze - a lot less nice): */ - -#define USE_COLOR - -/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ - -#define FANCY_BOXES - -/* Default timeout for fuzzed code (milliseconds). This is the upper bound, - also used for detecting hangs; the actual value is auto-scaled: */ - -#define EXEC_TIMEOUT 1000 - -/* Timeout rounding factor when auto-scaling (milliseconds): */ - -#define EXEC_TM_ROUND 20 - -/* Default memory limit for child process (MB): */ - -#ifndef __x86_64__ -# define MEM_LIMIT 25 -#else -# define MEM_LIMIT 50 -#endif /* ^!__x86_64__ */ - -/* Default memory limit when running in QEMU mode (MB): */ - -#define MEM_LIMIT_QEMU 200 - -/* Number of calibration cycles per every new test case (and for test - cases that show variable behavior): */ - -#define CAL_CYCLES 8 -#define CAL_CYCLES_LONG 40 - -/* Number of subsequent timeouts before abandoning an input file: */ - -#define TMOUT_LIMIT 250 - -/* Maximum number of unique hangs or crashes to record: */ - -#define KEEP_UNIQUE_HANG 500 -#define KEEP_UNIQUE_CRASH 5000 - -/* Baseline number of random tweaks during a single 'havoc' stage: */ - -#define HAVOC_CYCLES 256 -#define HAVOC_CYCLES_INIT 1024 - -/* Maximum multiplier for the above (should be a power of two, beware - of 32-bit int overflows): */ - -#define HAVOC_MAX_MULT 16 - -/* Absolute minimum number of havoc cycles (after all adjustments): */ - -#define HAVOC_MIN 16 - -/* Maximum stacking for havoc-stage tweaks. The actual value is calculated - like this: - - n = random between 1 and HAVOC_STACK_POW2 - stacking = 2^n - - In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or - 128 stacked tweaks: */ - -#define HAVOC_STACK_POW2 7 - -/* Caps on block sizes for cloning and deletion operations. Each of these - ranges has a 33% probability of getting picked, except for the first - two cycles where smaller blocks are favored: */ - -#define HAVOC_BLK_SMALL 32 -#define HAVOC_BLK_MEDIUM 128 -#define HAVOC_BLK_LARGE 1500 - -/* Extra-large blocks, selected very rarely (<5% of the time): */ - -#define HAVOC_BLK_XL 32768 - -/* Probabilities of skipping non-favored entries in the queue, expressed as - percentages: */ - -#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ -#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ -#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ - -/* Splicing cycle count: */ - -#define SPLICE_CYCLES 15 - -/* Nominal per-splice havoc cycle length: */ - -#define SPLICE_HAVOC 32 - -/* Maximum offset for integer addition / subtraction stages: */ - -#define ARITH_MAX 35 - -/* Limits for the test case trimmer. The absolute minimum chunk size; and - the starting and ending divisors for chopping up the input file: */ - -#define TRIM_MIN_BYTES 4 -#define TRIM_START_STEPS 16 -#define TRIM_END_STEPS 1024 - -/* Maximum size of input file, in bytes (keep under 100MB): */ - -#define MAX_FILE (1 * 1024 * 1024) - -/* The same, for the test case minimizer: */ - -#define TMIN_MAX_FILE (10 * 1024 * 1024) - -/* Block normalization steps for afl-tmin: */ - -#define TMIN_SET_MIN_SIZE 4 -#define TMIN_SET_STEPS 128 - -/* Maximum dictionary token size (-x), in bytes: */ - -#define MAX_DICT_FILE 128 - -/* Length limits for auto-detected dictionary tokens: */ - -#define MIN_AUTO_EXTRA 3 -#define MAX_AUTO_EXTRA 32 - -/* Maximum number of user-specified dictionary tokens to use in deterministic - steps; past this point, the "extras/user" step will be still carried out, - but with proportionally lower odds: */ - -#define MAX_DET_EXTRAS 200 - -/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing - (first value), and to keep in memory as candidates. The latter should be much - higher than the former. */ - -#define USE_AUTO_EXTRAS 50 -#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) - -/* Scaling factor for the effector map used to skip some of the more - expensive deterministic steps. The actual divisor is set to - 2^EFF_MAP_SCALE2 bytes: */ - -#define EFF_MAP_SCALE2 3 - -/* Minimum input file length at which the effector logic kicks in: */ - -#define EFF_MIN_LEN 128 - -/* Maximum effector density past which everything is just fuzzed - unconditionally (%): */ - -#define EFF_MAX_PERC 90 - -/* UI refresh frequency (Hz): */ - -#define UI_TARGET_HZ 5 - -/* Fuzzer stats file and plot update intervals (sec): */ - -#define STATS_UPDATE_SEC 60 -#define PLOT_UPDATE_SEC 5 - -/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ - -#define AVG_SMOOTHING 16 - -/* Sync interval (every n havoc cycles): */ - -#define SYNC_INTERVAL 5 - -/* Output directory reuse grace period (minutes): */ - -#define OUTPUT_GRACE 25 - -/* Uncomment to use simple file names (id_NNNNNN): */ - -// #define SIMPLE_FILES - -/* List of interesting values to use in fuzzing. */ - -#define INTERESTING_8 \ - -128, /* Overflow signed 8-bit when decremented */ \ - -1, /* */ \ - 0, /* */ \ - 1, /* */ \ - 16, /* One-off with common buffer size */ \ - 32, /* One-off with common buffer size */ \ - 64, /* One-off with common buffer size */ \ - 100, /* One-off with common buffer size */ \ - 127 /* Overflow signed 8-bit when incremented */ - -#define INTERESTING_16 \ - -32768, /* Overflow signed 16-bit when decremented */ \ - -129, /* Overflow signed 8-bit */ \ - 128, /* Overflow signed 8-bit */ \ - 255, /* Overflow unsig 8-bit when incremented */ \ - 256, /* Overflow unsig 8-bit */ \ - 512, /* One-off with common buffer size */ \ - 1000, /* One-off with common buffer size */ \ - 1024, /* One-off with common buffer size */ \ - 4096, /* One-off with common buffer size */ \ - 32767 /* Overflow signed 16-bit when incremented */ - -#define INTERESTING_32 \ - -2147483648LL, /* Overflow signed 32-bit when decremented */ \ - -100663046, /* Large negative number (endian-agnostic) */ \ - -32769, /* Overflow signed 16-bit */ \ - 32768, /* Overflow signed 16-bit */ \ - 65535, /* Overflow unsig 16-bit when incremented */ \ - 65536, /* Overflow unsig 16 bit */ \ - 100663045, /* Large positive number (endian-agnostic) */ \ - 2147483647 /* Overflow signed 32-bit when incremented */ - -/*********************************************************** - * * - * Really exotic stuff you probably don't want to touch: * - * * - ***********************************************************/ - -/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ - -#define RESEED_RNG 10000 - -/* Maximum line length passed from GCC to 'as' and used for parsing - configuration files: */ - -#define MAX_LINE 8192 - -/* Environment variable used to pass SHM ID to the called program. */ - -#define SHM_ENV_VAR "__AFL_SHM_ID" - -/* Other less interesting, internal-only variables. */ - -#define CLANG_ENV_VAR "__AFL_CLANG_MODE" -#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" -#define PERSIST_ENV_VAR "__AFL_PERSISTENT" -#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" - -/* In-code signatures for deferred and persistent mode. */ - -#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" -#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" - -/* Distinctive bitmap signature used to indicate failed execution: */ - -#define EXEC_FAIL_SIG 0xfee1dead - -/* Distinctive exit code used to indicate MSAN trip condition: */ - -#define MSAN_ERROR 86 - -/* Designated file descriptors for forkserver commands (the application will - use FORKSRV_FD and FORKSRV_FD + 1): */ - -#define FORKSRV_FD 198 - -/* Fork server init timeout multiplier: we'll wait the user-selected - timeout plus this much for the fork server to spin up. */ - -#define FORK_WAIT_MULT 10 - -/* Calibration timeout adjustments, to be a bit more generous when resuming - fuzzing sessions or trying to calibrate already-added internal finds. - The first value is a percentage, the other is in milliseconds: */ - -#define CAL_TMOUT_PERC 125 -#define CAL_TMOUT_ADD 50 - -/* Number of chances to calibrate a case before giving up: */ - -#define CAL_CHANCES 3 - -/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than - 2; you probably want to keep it under 18 or so for performance reasons - (adjusting AFL_INST_RATIO when compiling is probably a better way to solve - problems with complex programs). You need to recompile the target binary - after changing this - otherwise, SEGVs may ensue. */ - -#define MAP_SIZE_POW2 18 -#define MAP_SIZE (1 << MAP_SIZE_POW2) - -/* Maximum allocator request size (keep well under INT_MAX): */ - -#define MAX_ALLOC 0x40000000 - -/* A made-up hashing seed: */ - -#define HASH_CONST 0xa5b35705 - -/* Constants for afl-gotcpu to control busy loop timing: */ - -#define CTEST_TARGET_MS 5000 -#define CTEST_CORE_TRG_MS 1000 -#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) - -/* Uncomment this to use inferior block-coverage-based instrumentation. Note - that you need to recompile the target binary for this to have any effect: */ - -// #define COVERAGE_ONLY - -/* Uncomment this to ignore hit counts and output just one bit per tuple. - As with the previous setting, you will need to recompile the target - binary: */ - -// #define SKIP_COUNTS - -/* Uncomment this to use instrumentation data to record newly discovered paths, - but do not use them as seeds for fuzzing. This is useful for conveniently - measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ - -// #define IGNORE_FINDS - -#endif /* ! _HAVE_CONFIG_H */ diff --git a/AFL/debug.h b/AFL/debug.h deleted file mode 100755 index 5f75974..0000000 --- a/AFL/debug.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright 2013 Google LLC All rights reserved. - - 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. -*/ - -/* - american fuzzy lop - debug / error handling macros - -------------------------------------------------- - - Written and maintained by Michal Zalewski -*/ - -#ifndef _HAVE_DEBUG_H -#define _HAVE_DEBUG_H - -#include - -#include "types.h" -#include "config.h" - -/******************* - * Terminal colors * - *******************/ - -#ifdef USE_COLOR - -# define cBLK "\x1b[0;30m" -# define cRED "\x1b[0;31m" -# define cGRN "\x1b[0;32m" -# define cBRN "\x1b[0;33m" -# define cBLU "\x1b[0;34m" -# define cMGN "\x1b[0;35m" -# define cCYA "\x1b[0;36m" -# define cLGR "\x1b[0;37m" -# define cGRA "\x1b[1;90m" -# define cLRD "\x1b[1;91m" -# define cLGN "\x1b[1;92m" -# define cYEL "\x1b[1;93m" -# define cLBL "\x1b[1;94m" -# define cPIN "\x1b[1;95m" -# define cLCY "\x1b[1;96m" -# define cBRI "\x1b[1;97m" -# define cRST "\x1b[0m" - -# define bgBLK "\x1b[40m" -# define bgRED "\x1b[41m" -# define bgGRN "\x1b[42m" -# define bgBRN "\x1b[43m" -# define bgBLU "\x1b[44m" -# define bgMGN "\x1b[45m" -# define bgCYA "\x1b[46m" -# define bgLGR "\x1b[47m" -# define bgGRA "\x1b[100m" -# define bgLRD "\x1b[101m" -# define bgLGN "\x1b[102m" -# define bgYEL "\x1b[103m" -# define bgLBL "\x1b[104m" -# define bgPIN "\x1b[105m" -# define bgLCY "\x1b[106m" -# define bgBRI "\x1b[107m" - -#else - -# define cBLK "" -# define cRED "" -# define cGRN "" -# define cBRN "" -# define cBLU "" -# define cMGN "" -# define cCYA "" -# define cLGR "" -# define cGRA "" -# define cLRD "" -# define cLGN "" -# define cYEL "" -# define cLBL "" -# define cPIN "" -# define cLCY "" -# define cBRI "" -# define cRST "" - -# define bgBLK "" -# define bgRED "" -# define bgGRN "" -# define bgBRN "" -# define bgBLU "" -# define bgMGN "" -# define bgCYA "" -# define bgLGR "" -# define bgGRA "" -# define bgLRD "" -# define bgLGN "" -# define bgYEL "" -# define bgLBL "" -# define bgPIN "" -# define bgLCY "" -# define bgBRI "" - -#endif /* ^USE_COLOR */ - -/************************* - * Box drawing sequences * - *************************/ - -#ifdef FANCY_BOXES - -# define SET_G1 "\x1b)0" /* Set G1 for box drawing */ -# define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ -# define bSTART "\x0e" /* Enter G1 drawing mode */ -# define bSTOP "\x0f" /* Leave G1 drawing mode */ -# define bH "q" /* Horizontal line */ -# define bV "x" /* Vertical line */ -# define bLT "l" /* Left top corner */ -# define bRT "k" /* Right top corner */ -# define bLB "m" /* Left bottom corner */ -# define bRB "j" /* Right bottom corner */ -# define bX "n" /* Cross */ -# define bVR "t" /* Vertical, branch right */ -# define bVL "u" /* Vertical, branch left */ -# define bHT "v" /* Horizontal, branch top */ -# define bHB "w" /* Horizontal, branch bottom */ - -#else - -# define SET_G1 "" -# define RESET_G1 "" -# define bSTART "" -# define bSTOP "" -# define bH "-" -# define bV "|" -# define bLT "+" -# define bRT "+" -# define bLB "+" -# define bRB "+" -# define bX "+" -# define bVR "+" -# define bVL "+" -# define bHT "+" -# define bHB "+" - -#endif /* ^FANCY_BOXES */ - -/*********************** - * Misc terminal codes * - ***********************/ - -#define TERM_HOME "\x1b[H" -#define TERM_CLEAR TERM_HOME "\x1b[2J" -#define cEOL "\x1b[0K" -#define CURSOR_HIDE "\x1b[?25l" -#define CURSOR_SHOW "\x1b[?25h" - -/************************ - * Debug & error macros * - ************************/ - -/* Just print stuff to the appropriate stream. */ - -#ifdef MESSAGES_TO_STDOUT -# define SAYF(x...) printf(x) -#else -# define SAYF(x...) fprintf(stderr, x) -#endif /* ^MESSAGES_TO_STDOUT */ - -/* Show a prefixed warning. */ - -#define WARNF(x...) do { \ - SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Show a prefixed "doing something" message. */ - -#define ACTF(x...) do { \ - SAYF(cLBL "[*] " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Show a prefixed "success" message. */ - -#define OKF(x...) do { \ - SAYF(cLGN "[+] " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Show a prefixed fatal error message (not used in afl). */ - -#define BADF(x...) do { \ - SAYF(cLRD "\n[-] " cRST x); \ - SAYF(cRST "\n"); \ - } while (0) - -/* Die with a verbose non-OS fatal error message. */ - -#define FATAL(x...) do { \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ - cBRI x); \ - SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - exit(1); \ - } while (0) - -/* Die by calling abort() to provide a core dump. */ - -#define ABORT(x...) do { \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ - cBRI x); \ - SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - abort(); \ - } while (0) - -/* Die while also including the output of perror(). */ - -#define PFATAL(x...) do { \ - fflush(stdout); \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \ - cBRI x); \ - SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ - exit(1); \ - } while (0) - -/* Die with FAULT() or PFAULT() depending on the value of res (used to - interpret different failure modes for read(), write(), etc). */ - -#define RPFATAL(res, x...) do { \ - if (res < 0) PFATAL(x); else FATAL(x); \ - } while (0) - -/* Error-checking versions of read() and write() that call RPFATAL() as - appropriate. */ - -#define ck_write(fd, buf, len, fn) do { \ - u32 _len = (len); \ - s32 _res = write(fd, buf, _len); \ - if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ - } while (0) - -#define ck_read(fd, buf, len, fn) do { \ - u32 _len = (len); \ - s32 _res = read(fd, buf, _len); \ - if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ - } while (0) - -#endif /* ! _HAVE_DEBUG_H */ diff --git a/AFL/hash.h b/AFL/hash.h deleted file mode 100755 index e17fc8f..0000000 --- a/AFL/hash.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright 2016 Google LLC All rights reserved. - - 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. -*/ - -/* - american fuzzy lop - hashing function - ------------------------------------- - - The hash32() function is a variant of MurmurHash3, a good - non-cryptosafe hashing function developed by Austin Appleby. - - For simplicity, this variant does *NOT* accept buffer lengths - that are not divisible by 8 bytes. The 32-bit version is otherwise - similar to the original; the 64-bit one is a custom hack with - mostly-unproven properties. - - Austin's original code is public domain. - - Other code written and maintained by Michal Zalewski -*/ - -#ifndef _HAVE_HASH_H -#define _HAVE_HASH_H - -#include "types.h" - -#ifdef __x86_64__ - -#define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) - -static inline u32 hash32(const void* key, u32 len, u32 seed) { - - const u64* data = (u64*)key; - u64 h1 = seed ^ len; - - len >>= 3; - - while (len--) { - - u64 k1 = *data++; - - k1 *= 0x87c37b91114253d5ULL; - k1 = ROL64(k1, 31); - k1 *= 0x4cf5ad432745937fULL; - - h1 ^= k1; - h1 = ROL64(h1, 27); - h1 = h1 * 5 + 0x52dce729; - - } - - h1 ^= h1 >> 33; - h1 *= 0xff51afd7ed558ccdULL; - h1 ^= h1 >> 33; - h1 *= 0xc4ceb9fe1a85ec53ULL; - h1 ^= h1 >> 33; - - return h1; - -} - -#else - -#define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) - -static inline u32 hash32(const void* key, u32 len, u32 seed) { - - const u32* data = (u32*)key; - u32 h1 = seed ^ len; - - len >>= 2; - - while (len--) { - - u32 k1 = *data++; - - k1 *= 0xcc9e2d51; - k1 = ROL32(k1, 15); - k1 *= 0x1b873593; - - h1 ^= k1; - h1 = ROL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - - } - - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - return h1; - -} - -#endif /* ^__x86_64__ */ - -#endif /* !_HAVE_HASH_H */ diff --git a/AFL/types.h b/AFL/types.h deleted file mode 100755 index f4a5716..0000000 --- a/AFL/types.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright 2013 Google LLC All rights reserved. - - 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. -*/ - - -/* - american fuzzy lop - type definitions and minor macros - ------------------------------------------------------ - - Written and maintained by Michal Zalewski -*/ - -#ifndef _HAVE_TYPES_H -#define _HAVE_TYPES_H - -#include -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; - -/* - - Ugh. There is an unintended compiler / glibc #include glitch caused by - combining the u64 type an %llu in format strings, necessitating a workaround. - - In essence, the compiler is always looking for 'unsigned long long' for %llu. - On 32-bit systems, the u64 type (aliased to uint64_t) is expanded to - 'unsigned long long' in , so everything checks out. - - But on 64-bit systems, it is #ifdef'ed in the same file as 'unsigned long'. - Now, it only happens in circumstances where the type happens to have the - expected bit width, *but* the compiler does not know that... and complains - about 'unsigned long' being unsafe to pass to %llu. - - */ - -#ifdef __x86_64__ -typedef unsigned long long u64; -#else -typedef uint64_t u64; -#endif /* ^__x86_64__ */ - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -#ifndef MIN -# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) -# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) -#endif /* !MIN */ - -#define SWAP16(_x) ({ \ - u16 _ret = (_x); \ - (u16)((_ret << 8) | (_ret >> 8)); \ - }) - -#define SWAP32(_x) ({ \ - u32 _ret = (_x); \ - (u32)((_ret << 24) | (_ret >> 24) | \ - ((_ret << 8) & 0x00FF0000) | \ - ((_ret >> 8) & 0x0000FF00)); \ - }) - -#ifdef AFL_LLVM_PASS -# define AFL_R(x) (random() % (x)) -#else -# define R(x) (random() % (x)) -#endif /* ^AFL_LLVM_PASS */ - -#define STRINGIFY_INTERNAL(x) #x -#define STRINGIFY(x) STRINGIFY_INTERNAL(x) - -#define MEM_BARRIER() \ - __asm__ volatile("" ::: "memory") - -#define likely(_x) __builtin_expect(!!(_x), 1) -#define unlikely(_x) __builtin_expect(!!(_x), 0) - -#endif /* ! _HAVE_TYPES_H */ -- Gitee From 3328a4db4ea42bb39bcfba4d8fd8944da02e7a1f Mon Sep 17 00:00:00 2001 From: PengJiaScu Date: Thu, 16 Nov 2023 07:59:36 +0000 Subject: [PATCH 8/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20corp?= =?UTF-8?q?us?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- corpus/IR_config | 921 -------------------------------------- corpus/initlib/init_lib | 174 ------- corpus/input/alter_stmt | 5 - corpus/input/create_index | 5 - corpus/input/create_table | 5 - corpus/input/create_view | 4 - corpus/input/delete_stmt | 4 - corpus/input/update | 4 - 8 files changed, 1122 deletions(-) delete mode 100755 corpus/IR_config delete mode 100755 corpus/initlib/init_lib delete mode 100755 corpus/input/alter_stmt delete mode 100755 corpus/input/create_index delete mode 100755 corpus/input/create_table delete mode 100755 corpus/input/create_view delete mode 100755 corpus/input/delete_stmt delete mode 100755 corpus/input/update diff --git a/corpus/IR_config b/corpus/IR_config deleted file mode 100755 index b234045..0000000 --- a/corpus/IR_config +++ /dev/null @@ -1,921 +0,0 @@ -1 1 -3 2 3 0 3 -2 2 -3 3 0 2 3 -3 3 0 0 3 -3 11 -3 71 3 0 3 -3 65 3 0 3 -3 61 3 0 3 -3 123 3 0 3 -3 22 3 0 3 -3 23 3 0 3 -3 26 3 0 3 -3 4 3 0 3 -3 27 3 0 3 -3 37 3 0 3 -3 16 3 0 3 -4 2 -3 35 2 9 3 -3 35 2 12 3 -5 1 -3 196 3 34 3 -6 1 -3 158 3 5 3 -7 1 -3 173 3 6 3 -8 1 -3 269 3 7 3 -9 1 -3 13 1 8 3 -10 1 -3 162 3 158 3 -11 1 -3 25 1 10 3 -12 1 -3 13 3 11 3 -13 2 -3 0 3 0 3 -3 14 3 0 3 -14 2 -3 15 3 0 3 -3 15 3 14 3 -15 3 -4 0 3 0 3 -5 0 3 0 3 -6 0 3 0 3 -16 1 -7 269 3 17 3 -17 2 -3 18 3 0 3 -3 18 8 17 3 -18 18 -9 267 3 19 3 -11 82 10 0 3 -12 107 3 0 3 -13 267 3 20 3 -14 267 3 19 3 -15 267 3 0 3 -16 270 3 0 3 -17 0 3 0 3 -18 271 3 0 3 -19 270 3 0 3 -20 270 3 0 3 -22 267 21 206 10 -22 267 23 0 3 -22 267 24 104 3 -25 271 3 104 3 -26 269 3 0 3 -28 271 27 271 3 -29 267 27 267 3 -19 1 -3 85 3 21 3 -20 1 -3 267 3 19 3 -21 3 -3 0 3 0 3 -30 267 3 0 3 -31 0 3 0 3 -22 1 -18 271 32 269 3 -23 1 -33 24 3 25 3 -24 2 -3 0 3 0 3 -34 0 3 0 3 -25 2 -3 269 3 0 3 -3 269 8 25 3 -26 1 -35 24 3 25 3 -27 1 -3 35 36 33 3 -28 1 -3 196 3 34 3 -29 1 -3 158 3 28 3 -30 1 -3 57 3 29 3 -31 1 -3 162 24 30 3 -32 1 -3 60 3 31 3 -33 1 -3 36 3 32 3 -34 2 -3 0 3 0 3 -37 262 3 0 3 -35 2 -3 0 3 0 3 -3 201 3 0 3 -36 2 -3 0 3 0 3 -5 0 3 0 3 -37 3 -39 59 3 41 3 -39 59 3 44 3 -39 59 3 47 3 -38 1 -3 55 3 56 3 -39 1 -3 49 3 38 3 -40 1 -3 269 3 39 3 -41 1 -3 60 38 40 3 -42 1 -3 57 3 38 3 -43 1 -3 269 24 42 3 -44 1 -3 60 38 43 3 -45 1 -3 48 3 56 3 -46 1 -3 269 3 45 3 -47 1 -3 60 38 46 3 -48 2 -3 124 3 0 3 -40 170 10 124 3 -49 2 -41 50 3 0 3 -40 170 42 50 3 -50 2 -3 51 3 0 3 -3 51 8 50 3 -51 1 -40 52 10 0 3 -52 2 -3 0 3 0 3 -3 53 3 0 3 -53 2 -3 54 3 0 3 -3 54 8 53 3 -54 2 -3 206 3 0 3 -43 0 3 0 3 -55 2 -3 0 3 0 3 -44 269 3 169 3 -56 2 -3 0 3 0 3 -45 57 3 0 3 -57 2 -3 58 3 0 3 -3 58 8 57 3 -58 1 -3 257 46 54 3 -59 4 -3 0 3 0 3 -5 0 3 0 3 -47 0 3 0 3 -48 0 3 0 3 -60 2 -3 0 3 0 3 -6 0 3 0 3 -61 1 -50 64 49 63 3 -62 1 -3 269 40 117 10 -63 1 -3 271 32 62 3 -64 2 -3 0 3 0 3 -51 0 3 0 3 -65 1 -50 69 3 68 3 -66 1 -3 169 44 124 3 -67 1 -3 272 3 66 3 -68 1 -3 70 52 67 3 -69 2 -3 0 3 0 3 -53 0 3 0 3 -70 4 -3 0 3 0 3 -54 0 3 0 3 -55 0 3 0 3 -56 0 3 0 3 -71 2 -50 77 57 74 3 -50 77 57 76 3 -72 1 -3 82 10 79 3 -73 1 -3 269 40 72 3 -74 1 -3 78 3 73 3 -75 1 -3 269 3 80 3 -76 1 -3 78 3 75 3 -77 2 -3 0 3 0 3 -58 0 3 0 3 -78 2 -3 0 3 0 3 -59 0 3 0 3 -79 2 -3 0 3 0 3 -3 80 3 0 3 -80 2 -3 81 44 124 3 -44 124 3 0 3 -81 2 -60 0 3 0 3 -6 0 3 0 3 -82 2 -3 83 3 0 3 -3 83 8 82 3 -83 2 -3 84 3 0 3 -3 107 3 0 3 -84 1 -3 267 3 85 3 -85 1 -3 86 3 99 3 -86 3 -3 89 3 0 3 -3 88 3 0 3 -3 87 3 0 3 -87 13 -61 254 3 0 3 -62 254 3 0 3 -63 255 3 0 3 -64 255 3 0 3 -65 0 3 0 3 -66 0 3 0 3 -67 0 3 0 3 -68 0 3 0 3 -69 254 3 0 3 -70 0 3 0 3 -71 0 3 0 3 -72 0 3 0 3 -73 0 3 0 3 -88 2 -74 0 3 0 3 -75 0 3 0 3 -89 3 -3 95 3 96 3 -3 93 3 90 3 -3 92 3 91 3 -90 1 -3 94 3 96 3 -91 1 -3 252 3 96 3 -92 4 -76 0 3 0 3 -77 0 3 0 3 -78 0 3 0 3 -79 0 3 0 3 -93 2 -80 0 3 0 3 -81 0 3 0 3 -94 2 -3 0 3 0 3 -3 253 3 0 3 -95 5 -82 0 3 0 3 -83 0 3 0 3 -84 0 3 0 3 -85 0 3 0 3 -86 0 3 0 3 -96 2 -3 0 3 0 3 -3 97 3 0 3 -97 2 -3 98 3 0 3 -3 98 3 97 3 -98 3 -87 0 3 0 3 -88 0 3 0 3 -89 0 3 0 3 -99 2 -3 0 3 0 3 -3 100 3 0 3 -100 2 -3 101 3 0 3 -3 101 3 100 3 -101 3 -3 103 3 0 3 -3 102 3 0 3 -3 104 3 0 3 -102 1 -90 206 10 0 3 -103 1 -91 0 3 0 3 -104 2 -92 0 3 0 3 -93 0 3 0 3 -105 2 -3 0 3 0 3 -94 270 3 0 3 -106 1 -95 206 10 0 3 -107 4 -49 122 40 117 10 -3 105 3 109 3 -3 105 3 106 3 -3 105 96 111 3 -108 1 -3 122 40 117 10 -109 1 -3 121 3 108 3 -110 1 -3 116 10 112 3 -111 1 -3 122 40 110 3 -112 1 -97 269 40 113 3 -113 1 -3 170 10 114 3 -114 5 -3 0 3 0 3 -98 115 3 0 3 -99 115 3 0 3 -98 115 99 115 3 -99 115 98 115 3 -115 4 -100 0 3 0 3 -101 0 3 0 3 -102 0 3 0 3 -103 0 3 0 3 -116 2 -3 119 3 0 3 -3 119 8 116 3 -117 2 -3 118 3 0 3 -3 118 8 117 3 -118 2 -3 119 3 0 3 -40 206 10 148 3 -119 2 -3 267 3 148 3 -3 267 40 120 3 -120 1 -3 262 10 148 3 -121 2 -104 0 3 0 3 -51 0 3 0 3 -122 2 -3 0 3 0 3 -3 271 3 0 3 -123 1 -3 124 3 0 3 -124 2 -3 127 3 125 3 -3 201 3 126 3 -125 1 -3 196 3 198 3 -126 1 -3 127 3 125 3 -127 5 -3 129 3 0 3 -3 194 3 0 3 -3 127 105 128 3 -3 127 106 128 3 -3 127 107 128 3 -128 1 -3 195 3 127 3 -129 1 -3 130 3 0 3 -130 1 -108 191 3 135 3 -131 1 -3 155 3 136 3 -132 1 -3 156 3 131 3 -133 1 -3 158 3 132 3 -134 1 -3 160 3 133 3 -135 1 -3 188 3 134 3 -136 2 -3 0 3 0 3 -109 137 3 0 3 -137 2 -3 138 3 0 3 -3 138 8 137 3 -138 1 -3 268 44 139 3 -139 1 -40 140 10 0 3 -140 1 -3 143 3 142 3 -141 1 -3 145 3 149 3 -142 1 -3 144 3 141 3 -143 2 -3 0 3 0 3 -3 268 3 0 3 -144 2 -3 0 3 0 3 -110 205 3 0 3 -145 2 -3 0 3 0 3 -111 146 3 0 3 -146 2 -3 147 3 0 3 -3 147 8 146 3 -147 1 -3 206 3 148 3 -148 3 -3 0 3 0 3 -112 0 3 0 3 -113 0 3 0 3 -149 2 -3 0 3 0 3 -3 150 3 151 3 -150 2 -114 0 3 0 3 -115 0 3 0 3 -151 2 -3 152 3 0 3 -3 153 3 0 3 -152 3 -116 0 3 0 3 -3 262 117 0 3 -118 0 3 0 3 -153 1 -120 152 119 154 3 -154 3 -3 152 3 0 3 -121 0 3 0 3 -3 262 122 0 3 -155 2 -3 0 3 0 3 -123 206 3 0 3 -156 2 -3 0 3 0 3 -124 205 3 157 3 -157 2 -3 0 3 0 3 -125 0 3 0 3 -158 2 -3 0 3 0 3 -3 159 3 0 3 -159 1 -126 206 3 0 3 -160 2 -3 0 3 0 3 -3 161 3 0 3 -161 1 -1 162 3 0 3 -162 2 -3 163 3 0 3 -3 163 8 162 3 -163 2 -3 164 3 0 3 -3 174 3 0 3 -164 4 -3 172 3 0 3 -3 167 3 0 3 -3 166 3 0 3 -3 165 3 0 3 -165 1 -40 163 8 162 10 -166 1 -40 174 10 0 3 -167 2 -3 171 44 168 3 -127 171 44 168 3 -168 1 -3 266 3 169 3 -169 2 -3 0 3 0 3 -40 170 10 0 3 -170 2 -3 267 3 0 3 -3 267 8 170 3 -171 1 -3 194 3 0 3 -172 1 -3 269 3 173 3 -173 2 -3 0 3 0 3 -44 266 3 0 3 -174 6 -3 163 3 176 3 -3 163 3 178 3 -3 163 3 179 3 -3 163 3 180 3 -3 163 3 181 3 -3 163 3 182 3 -175 1 -3 163 32 206 3 -176 1 -3 183 3 175 3 -177 1 -3 163 128 170 10 -178 1 -3 183 3 177 3 -179 1 -3 187 3 175 3 -180 1 -3 187 3 177 3 -181 1 -3 183 3 163 3 -182 1 -3 184 3 164 3 -183 4 -129 0 3 0 3 -130 0 3 0 3 -131 0 3 0 3 -132 0 3 0 3 -184 3 -133 185 129 0 3 -134 186 129 0 3 -135 186 129 0 3 -185 2 -3 0 3 0 3 -136 0 3 0 3 -186 2 -3 0 3 0 3 -137 0 3 0 3 -187 2 -138 186 129 0 3 -139 186 129 0 3 -188 2 -3 189 3 0 3 -3 189 8 188 3 -189 2 -3 190 3 0 3 -3 206 3 173 3 -190 2 -140 0 3 0 3 -3 269 141 0 3 -191 2 -3 0 3 0 3 -3 192 3 0 3 -192 2 -3 193 3 0 3 -3 193 3 192 3 -193 9 -142 0 3 0 3 -132 0 3 0 3 -48 0 3 0 3 -143 0 3 0 3 -144 0 3 0 3 -145 0 3 0 3 -146 0 3 0 3 -147 0 3 0 3 -148 0 3 0 3 -194 2 -40 194 10 0 3 -40 124 10 0 3 -195 3 -3 0 3 0 3 -143 0 3 0 3 -148 0 3 0 3 -196 2 -3 0 3 0 3 -3 197 3 0 3 -197 1 -111 146 3 0 3 -198 2 -3 0 3 0 3 -3 199 3 0 3 -199 1 -37 200 3 0 3 -200 2 -3 262 3 0 3 -3 262 8 262 3 -201 2 -149 202 3 0 3 -150 202 3 0 3 -202 2 -3 203 3 0 3 -3 203 8 202 3 -203 1 -3 269 3 204 3 -204 1 -3 169 44 171 3 -205 2 -3 206 3 0 3 -3 206 8 205 3 -206 1 -3 207 3 0 3 -207 11 -3 207 151 207 3 -3 207 152 207 3 -3 207 119 207 3 -153 207 3 0 3 -3 208 154 0 3 -3 208 155 0 3 -3 208 156 0 3 -3 208 157 0 3 -3 208 158 0 3 -3 208 159 0 3 -3 208 3 0 3 -208 5 -3 208 160 0 3 -3 208 161 0 3 -3 208 3 209 3 -3 208 3 210 3 -3 211 3 0 3 -209 1 -3 258 3 211 3 -210 1 -3 258 3 259 3 -211 13 -3 214 3 260 3 -3 214 162 207 10 -3 214 162 212 3 -3 214 163 207 10 -3 214 163 212 3 -3 214 120 213 3 -3 214 164 213 3 -3 214 165 214 3 -3 214 166 215 3 -3 214 167 215 3 -3 214 168 214 3 -3 214 169 214 3 -3 214 3 0 3 -212 1 -3 207 8 261 10 -213 1 -3 214 119 211 3 -214 11 -3 214 170 214 3 -3 214 171 214 3 -3 214 172 214 3 -3 214 173 214 3 -3 214 174 214 3 -3 214 175 214 3 -3 214 140 214 3 -3 214 176 214 3 -3 214 177 214 3 -3 214 178 214 3 -3 215 3 0 3 -215 15 -3 257 3 0 3 -3 256 3 0 3 -3 262 3 0 3 -3 263 3 0 3 -3 264 3 0 3 -174 215 3 0 3 -175 215 3 0 3 -179 215 3 0 3 -3 171 3 0 3 -180 171 3 0 3 -3 250 3 0 3 -3 244 3 0 3 -90 257 10 0 3 -3 216 3 0 3 -40 207 10 0 3 -216 5 -3 242 3 0 3 -3 221 3 0 3 -3 217 3 0 3 -3 232 3 0 3 -3 223 3 0 3 -217 44 -181 207 10 0 3 -182 207 10 0 3 -183 207 10 0 3 -184 207 10 0 3 -185 207 10 0 3 -186 207 10 0 3 -187 207 10 0 3 -188 207 10 0 3 -189 207 10 0 3 -190 207 10 0 3 -191 207 10 0 3 -192 207 10 0 3 -193 207 10 0 3 -194 207 10 0 3 -195 207 10 0 3 -196 207 10 0 3 -197 207 10 0 3 -198 207 10 0 3 -199 207 8 207 10 -200 207 8 207 10 -201 207 8 207 10 -202 207 8 207 10 -203 207 8 207 10 -204 207 8 207 10 -205 207 8 207 10 -206 207 1 207 10 -207 207 1 207 10 -194 207 1 207 10 -208 207 8 218 3 -202 207 8 218 3 -209 207 8 218 3 -210 207 8 218 3 -211 207 8 218 3 -205 207 8 218 3 -212 207 8 218 3 -208 207 8 219 3 -213 207 8 219 3 -208 207 8 220 3 -214 261 10 0 3 -215 261 10 0 3 -216 207 8 261 10 -217 207 8 261 10 -218 207 8 261 10 -219 207 8 261 10 -218 1 -3 207 8 207 10 -219 1 -3 207 8 218 3 -220 1 -3 207 8 219 3 -221 29 -220 0 3 0 3 -221 0 3 0 3 -222 207 10 0 3 -223 207 10 0 3 -224 207 10 0 3 -225 207 10 0 3 -226 207 10 0 3 -227 207 10 0 3 -228 207 10 0 3 -229 207 10 0 3 -230 207 10 0 3 -231 207 10 0 3 -232 207 10 0 3 -233 207 10 0 3 -234 207 10 0 3 -235 207 10 0 3 -236 207 10 0 3 -237 207 10 0 3 -238 207 10 0 3 -239 207 10 0 3 -240 207 10 0 3 -225 207 8 207 10 -241 207 8 207 10 -242 207 8 207 10 -243 207 8 207 10 -244 207 8 207 10 -236 207 8 207 10 -245 207 8 207 10 -246 207 8 222 3 -222 1 -3 207 8 207 10 -223 11 -247 240 3 0 3 -248 240 3 0 3 -249 240 3 0 3 -250 240 3 0 3 -251 240 3 0 3 -252 262 10 240 3 -253 207 3 225 3 -254 207 3 225 3 -255 207 10 224 3 -256 207 10 224 3 -257 207 8 227 3 -224 1 -3 228 3 240 3 -225 1 -3 230 10 224 3 -226 1 -3 229 3 224 3 -227 1 -3 262 10 226 3 -228 3 -3 0 3 0 3 -258 0 3 0 3 -259 0 3 0 3 -229 3 -3 0 3 0 3 -260 0 3 0 3 -261 0 3 0 3 -230 2 -3 0 3 0 3 -3 231 3 0 3 -231 2 -8 262 3 0 3 -8 262 8 207 3 -232 15 -262 238 3 233 3 -263 207 10 239 3 -264 207 10 239 3 -265 207 10 239 3 -266 239 3 0 3 -267 207 10 239 3 -268 261 10 239 3 -269 238 3 233 3 -270 238 3 233 3 -271 238 3 233 3 -272 207 10 239 3 -273 207 10 239 3 -274 207 10 239 3 -275 207 10 239 3 -276 238 3 236 3 -233 1 -3 207 10 239 3 -234 1 -3 237 10 239 3 -235 1 -3 196 3 234 3 -236 1 -3 261 3 235 3 -237 2 -3 0 3 0 3 -277 264 3 0 3 -238 2 -3 0 3 0 3 -143 0 3 0 3 -239 2 -3 0 3 0 3 -3 240 3 0 3 -240 1 -278 241 3 0 3 -241 2 -3 268 3 0 3 -3 139 3 0 3 -242 3 -279 207 8 243 3 -280 207 8 207 10 -281 207 8 207 10 -243 1 -3 207 8 207 10 -244 1 -283 248 3 245 3 -245 1 -3 246 3 249 282 -246 2 -3 247 3 0 3 -3 247 3 246 3 -247 1 -285 207 284 207 3 -248 2 -3 0 3 0 3 -3 207 3 0 3 -249 2 -3 0 3 0 3 -286 207 3 0 3 -250 2 -287 207 44 251 10 -288 207 8 251 10 -251 8 -62 254 3 0 3 -61 254 3 0 3 -289 254 3 0 3 -87 0 3 0 3 -88 0 3 0 3 -77 252 3 0 3 -80 0 3 0 3 -76 254 3 0 3 -252 3 -3 0 3 0 3 -3 255 3 0 3 -3 253 3 0 3 -253 1 -40 262 8 262 10 -254 2 -3 0 3 0 3 -3 255 3 0 3 -255 1 -40 262 10 0 3 -256 3 -290 0 3 0 3 -291 0 3 0 3 -292 0 3 0 3 -257 2 -3 267 3 0 3 -3 269 293 267 3 -258 6 -46 0 3 0 3 -294 0 3 0 3 -295 0 3 0 3 -296 0 3 0 3 -297 0 3 0 3 -298 0 3 0 3 -259 3 -148 171 3 0 3 -299 171 3 0 3 -300 171 3 0 3 -260 2 -301 171 3 0 3 -302 171 3 0 3 -261 2 -3 207 3 0 3 -3 207 8 261 3 -262 1 -3 0 3 0 3 -263 1 -3 0 3 0 3 -264 1 -3 0 3 0 3 -265 1 -3 0 3 0 3 -266 1 -3 265 3 0 3 -267 1 -3 265 3 0 3 -268 1 -3 265 3 0 3 -269 1 -3 265 3 0 3 -270 1 -3 265 3 0 3 -271 1 -3 265 3 0 3 -272 1 -3 265 3 0 3 diff --git a/corpus/initlib/init_lib b/corpus/initlib/init_lib deleted file mode 100755 index 0f64f08..0000000 --- a/corpus/initlib/init_lib +++ /dev/null @@ -1,174 +0,0 @@ -CREATE TABLE t0 ( c0 INT UNSIGNED NOT NULL) ; -CREATE TABLE t0 ( c0 DOUBLE ( 1 , 1) VISIBLE ) ; -CREATE TABLE t0 ( c0 DECIMAL ( 1 ) DEFAULT ( 1 ) ) ; -CREATE TABLE t0 ( c0 BOOL ) ; -CREATE TABLE t0 ( c0 CHAR ) ; -CREATE TABLE t0 ( c0 INT , INDEX i0 ( c0 ASC ) ) ; -CREATE TABLE t0 ( c0 TEXT , INDEX i0 ( c0 ( 1 ) ) ) ; -CREATE TABLE t0 ( c0 INT , INDEX i0 ( ( c0 + 1 ) ) ) ; -CREATE TABLE t0 ( c0 INT , CONSTRAINT cc0 UNIQUE i0 ( c0 ) ) ; -CREATE TABLE t0 ( c0 INT , CONSTRAINT cc0 CHECK ( c0 = 1 ) ) ; -CREATE TABLE t0 ( c0 INT , c1 INT , UNIQUE ( c1 ) , CONSTRAINT cc0 FOREIGN KEY i0 ( c0 ) REFERENCES t0 ( c1 ) ON UPDATE CASCADE ON DELETE CASCADE ) ; -CREATE TABLE t0 REPLACE AS SELECT 1 ; -CREATE OR REPLACE ALGORITHM = TEMPTABLE VIEW v0 ( c0 , c1 ) AS SELECT 1 , 2 ; -CREATE UNIQUE INDEX i0 ON t0 ( c0 ) ; -DROP INDEX i0 ON t0 ; -DROP TABLE IF EXISTS t0 , t1 ; -DROP VIEW IF EXISTS v0 , v1 ; -DELETE QUICK FROM t0 LIMIT 1 ; -DELETE t0 FROM t0 ; -UPDATE t0 SET c0 = 1 ; -INSERT INTO t0 ( c0 ) VALUES ( 1 ) AS t1 ( c1 ) ON DUPLICATE KEY UPDATE c0 = 1 ; -INSERT INTO t0 SET c0 = 1 ; -INSERT INTO t0 ( c1 ) SELECT 1 ; -ALTER TABLE t0 ADD COLUMN c1 INT AFTER c0 ; -ALTER TABLE t0 ADD COLUMN ( c1 INT , UNIQUE ( c1 ) ) ; -ALTER TABLE t0 ADD UNIQUE ( c0 ) ; -ALTER TABLE t0 CHANGE COLUMN c0 c1 INT ; -ALTER TABLE t0 MODIFY COLUMN c0 INT FIRST; -ALTER TABLE t0 DROP COLUMN c0 ; -ALTER TABLE t0 DROP FOREIGN KEY cc0 ; -ALTER TABLE t0 DROP PRIMARY KEY ; -ALTER TABLE t0 DROP INDEX i0 ; -ALTER TABLE t0 DROP CHECK cc0 ; -ALTER TABLE t0 DROP CONSTRAINT cc0 ; -ALTER TABLE t0 ALTER COLUMN c0 SET DEFAULT ( 1 ) ; -ALTER TABLE t0 ALTER COLUMN c0 DROP DEFAULT ; -ALTER TABLE t0 ALTER COLUMN c0 SET INVISIBLE ; -ALTER TABLE t0 ALTER INDEX i0 INVISIBLE ; -ALTER TABLE t0 RENAME TO t1 ; -ALTER TABLE t0 RENAME INDEX i0 TO i1 ; -ALTER TABLE t0 RENAME COLUMN c0 TO c1 ; -SELECT c0 FROM t0 ORDER BY c0 LIMIT 1 ; -( SELECT c0 FROM t0 ) ORDER BY c0 LIMIT 1 ; -SELECT c0 FROM t0 UNION SELECT c0 FROM t0 ; -SELECT SQL_NO_CACHE c0 AS c1 FROM ( SELECT c0 FROM t0 ) AS t1 ( c2 ) WHERE c1 = 0 GROUP BY c1 HAVING c1 = 0 ; -SELECT c0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) ; -SELECT t0 . c0 FROM ( t0 CROSS JOIN t0 AS t1 ) ; -SELECT t0 . c0 FROM ( t0 , t0 AS t1 ) ; -SELECT t0 . c0 FROM t0 INNER JOIN t0 AS t1 ON t0 . c0 = t1 . c0 ; -SELECT t0 . c0 FROM t0 INNER JOIN t0 AS t1 USING ( c0 ) ; -SELECT t0 . c0 FROM t0 INNER JOIN t0 AS t1 ; -SELECT t0 . c0 FROM t0 LEFT OUTER JOIN t0 AS t1 ON t0 . c0 = t0 . c1 ; -SELECT t0 . c0 FROM t0 NATURAL INNER JOIN t0 AS t1 ; -WITH t1 ( c1 ) AS ( SELECT 1 ) SELECT c1 FROM t1 ; -WITH RECURSIVE t1 ( c1 ) AS ( SELECT 1 UNION SELECT c1 + 1 FROM t1 WHERE c1 < 10 ) SELECT c1 FROM t1 ; -SELECT * FROM t0 ; -SELECT c0 = ( SELECT c0 FROM t0 LIMIT 1 ) FROM t0 ; -SELECT c0 = ALL ( SELECT c0 FROM t0 ) FROM t0 ; -SELECT c0 IN ( SELECT c0 FROM t0 ) FROM t0 ; -SELECT TRUE ; -SELECT 1 ; -SELECT 1.1 ; -SELECT 'string' ; -SELECT CAST ( c0 AS UNSIGNED ) FROM t0 ; -SELECT CONVERT ( c0 , UNSIGNED ) FROM t0 ; -SELECT CASE c0 WHEN 1 THEN 1 ELSE 2 END FROM t0 ; -SELECT DEFAULT ( c0 ) FROM t0 ; -SELECT IF ( c0 , c0 , 1 ) FROM t0 ; -SELECT IFNULL ( c0 , 1 ) FROM t0 ; -SELECT NULLIF ( c0 , 1 ) FROM t0 ; -SELECT PI ( ) ; -SELECT RAND ( ) ; -SELECT ABS ( c0 ) FROM t0 ; -SELECT ACOS ( c0 ) FROM t0 ; -SELECT ASIN ( c0 ) FROM t0 ; -SELECT ATAN ( c0 ) FROM t0 ; -SELECT CEILING ( c0 ) FROM t0 ; -SELECT COS ( c0 ) FROM t0 ; -SELECT COT ( c0 ) FROM t0 ; -SELECT DEGREES ( c0 ) FROM t0 ; -SELECT EXP ( c0 ) FROM t0 ; -SELECT FLOOR ( c0 ) FROM t0 ; -SELECT HEX ( c0 ) FROM t0 ; -SELECT LN ( c0 ) FROM t0 ; -SELECT RADIANS ( c0 ) FROM t0 ; -SELECT RAND ( c0 ) FROM t0 ; -SELECT ROUND ( c0 ) FROM t0 ; -SELECT SIGN ( c0 ) FROM t0 ; -SELECT SIN ( c0 ) FROM t0 ; -SELECT SQRT ( c0 ) FROM t0 ; -SELECT TAN ( c0 ) FROM t0 ; -SELECT ATAN ( 1 , 1 ); -SELECT FORMAT ( 1 , 1 ); -SELECT LOG ( 1 , 1 ); -SELECT MOD ( 1 , 1 ); -SELECT POW ( 1 , 1 ); -SELECT ROUND ( 1 , 1 ); -SELECT TRUNCATE ( 1 , 1 ); -SELECT CONV ( 1 , 1 , 1 ) ; -SELECT ASCII ( c0 ) FROM t0 ; -SELECT BIN ( c0 ) FROM t0 ; -SELECT BIT_LENGTH ( c0 ) FROM t0 ; -SELECT CHAR_LENGTH ( c0 ) FROM t0 ; -SELECT LENGTH ( c0 ) FROM t0 ; -SELECT LOWER ( c0 ) FROM t0 ; -SELECT LTRIM ( c0 ) FROM t0 ; -SELECT OCT ( c0 ) FROM t0 ; -SELECT ORD ( c0 ) FROM t0 ; -SELECT QUOTE ( c0 ) FROM t0 ; -SELECT REVERSE ( c0 ) FROM t0 ; -SELECT RTRIM ( c0 ) FROM t0 ; -SELECT SPACE ( c0 ) FROM t0 ; -SELECT TRIM( c0 ) FROM t0 ; -SELECT TRIM( LEADING FROM c0 ) FROM t0 ; -SELECT TRIM( TRAILING FROM c0 ) FROM t0 ; -SELECT UNHEX ( c0 ) FROM t0 ; -SELECT UPPER ( c0 ) FROM t0 ; -SELECT FIND_IN_SET ( c0 , 'str' ) FROM t0 ; -SELECT INSTR ( c0 , 'str' ) FROM t0 ; -SELECT LEFT ( c0 , 'str' ) FROM t0 ; -SELECT LOCATE ( c0 , 'str' ) FROM t0 ; -SELECT REPEAT ( c0 , 'str' ) FROM t0 ; -SELECT RIGHT ( c0 , 'str' ) FROM t0 ; -SELECT SUBSTRING( c0 , 'str' ) FROM t0 ; -SELECT TRIM( LEADING c0 FROM 'str' ) FROM t0 ; -SELECT TRIM( TRAILING c0 FROM 'str' ) FROM t0 ; -SELECT TRIM( c0 FROM 'str' ) FROM t0 ; -SELECT EXPORT_SET ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT LOCATE ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT LPAD ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT REPLACE ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT RPAD ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT SUBSTRING( c0 , 'str' , 'str' ) FROM t0 ; -SELECT SUBSTRING_INDEX ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT EXPORT_SET ( c0 , 'str' , 'str' , 'str' ) FROM t0 ; -SELECT INSERT ( c0 , 'str' , 'str' , 'str' ) FROM t0 ; -SELECT EXPORT_SET ( c0 , 'str' , 'str' , 'str' , 'str' ) FROM t0 ; -SELECT CHAR ( c0 , 'str' ) FROM t0 ; -SELECT CONCAT ( c0 , 'str' ) FROM t0 ; -SELECT CONCAT_WS ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT ELT ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT FIELD ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT MAKE_SET ( c0 , 'str' , 'str' ) FROM t0 ; -SELECT AVG ( c0 ) FROM t0 ; -SELECT BIT_AND( c0 ) FROM t0 ; -SELECT BIT_OR( c0 ) FROM t0 ; -SELECT BIT_XOR( c0 ) FROM t0 ; -SELECT COUNT( * ) FROM t0 ; -SELECT COUNT( c0 ) FROM t0 ; -SELECT COUNT( DISTINCT c0 , 1 ) FROM t0 ; -SELECT MIN( c0 ) FROM t0 ; -SELECT MAX( c0 ) FROM t0 ; -SELECT SUM( c0 ) FROM t0 ; -SELECT STD( c0 ) FROM t0 ; -SELECT STDDEV_SAMP( c0 ) FROM t0 ; -SELECT VARIANCE( c0 ) FROM t0 ; -SELECT VAR_SAMP( c0 ) FROM t0 ; -SELECT GROUP_CONCAT( c0 , 1 ORDER BY c0 SEPARATOR ',' ) FROM t0 ; -SELECT ROW_NUMBER ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT RANK ( ) OVER ( PARTITION BY c0 ) FROM t0 ; -SELECT DENSE_RANK ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT CUME_DIST ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT PERCENT_RANK ( ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT NTILE ( 1 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT LEAD ( c0 , 1 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT LAG ( c0 , 1 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT FIRST_VALUE ( c0 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT LAST_VALUE ( c0 ) OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT NTH_VALUE ( c0 , 1 ) FROM FIRST RESPECT NULLS OVER w0 FROM t0 WINDOW w0 AS ( PARTITION BY c0 ) ; -SELECT 1 IN ( 1 , 2 , 3) ; -SELECT 1 NOT IN ( 1 , 2 , 3) ; -SELECT 1 BETWEEN 1 AND 2 ; -SELECT 1 NOT BETWEEN 1 AND 2 ; -SELECT 1 FROM t0 LEFT OUTER JOIN t1 USING ( c0 ) ; \ No newline at end of file diff --git a/corpus/input/alter_stmt b/corpus/input/alter_stmt deleted file mode 100755 index a5ca0a5..0000000 --- a/corpus/input/alter_stmt +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE t0 ( c0 INT , c1 INT ) ; -INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; -ALTER TABLE t0 ADD COLUMN c2 INT AFTER c0 ; -INSERT INTO t0 VALUES ( 1 , 2 , 3 ) , ( 3 , 4 , 5 ) ; -SELECT t0 . c0 FROM ( SELECT c1 FROM t0 ) AS t1 JOIN t0 ON t1 . c1 = t0 . c1 ; \ No newline at end of file diff --git a/corpus/input/create_index b/corpus/input/create_index deleted file mode 100755 index 0e9e16c..0000000 --- a/corpus/input/create_index +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE t0 ( c0 INT , c1 INT ) ; -INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; -CREATE INDEX i0 ON t0 ( c0 ) ; -INSERT INTO t0 VALUES ( 5 , 6 ) , ( 7 , 8 ) ; -SELECT t0 . c0 FROM ( SELECT c1 FROM t0 ) AS t1 JOIN t0 ON t1 . c1 = t0 . c1 ; \ No newline at end of file diff --git a/corpus/input/create_table b/corpus/input/create_table deleted file mode 100755 index b308ab5..0000000 --- a/corpus/input/create_table +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE t0 ( c0 INT , c1 INT ) ; -CREATE TABLE t1 ( c0 INT , c1 INT ) ; -INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; -INSERT INTO t0 VALUES ( 5 , 6 ) , ( 7 , 8 ) ; -SELECT t0 . c0 FROM t0 CROSS JOIN t1 ; \ No newline at end of file diff --git a/corpus/input/create_view b/corpus/input/create_view deleted file mode 100755 index 90504ac..0000000 --- a/corpus/input/create_view +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE t0 ( c0 INT , c1 INT ) ; -INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; -CREATE VIEW v0 AS SELECT c0 , c1 , 1 AS c2 FROM t0 ; -WITH t1 AS ( SELECT 1 AS c0 , 2 AS c2 ) SELECT t0 . c0 FROM t0 JOIN t1 ON t0 . c1 = t1 . c2 WHERE t0 . c0 = 0 ; diff --git a/corpus/input/delete_stmt b/corpus/input/delete_stmt deleted file mode 100755 index ae2f664..0000000 --- a/corpus/input/delete_stmt +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE t0 ( c0 INT , c1 INT ) ; -INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; -DELETE FROM t0 WHERE c0 = 1 ; -SELECT t0 . c0 FROM t0 AS t1 JOIN t0 ON t1 . c1 = t0 . c1 ; \ No newline at end of file diff --git a/corpus/input/update b/corpus/input/update deleted file mode 100755 index b3d7d35..0000000 --- a/corpus/input/update +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE t0 ( c0 INT , c1 INT ) ; -INSERT INTO t0 VALUES ( 1 , 2 ) , ( 3 , 4 ) ; -UPDATE t0 SET c0 = 5 WHERE c0 = 1 ; -WITH t1 AS ( SELECT c0 AS c2 FROM t0 ) SELECT c0 FROM t0 CROSS JOIN t1 WHERE c2 = 2 ; \ No newline at end of file -- Gitee From aea7adcdf325a59fe996c45bed32bd92032815ed Mon Sep 17 00:00:00 2001 From: Wen Xin Date: Thu, 16 Nov 2023 16:17:29 +0800 Subject: [PATCH 9/9] Fuzzer --- AFL/Makefile | 47 + AFL/afl-as.h | 727 ++++++ AFL/afl-fuzz.c | 6606 +++++++++++++++++++++++++++++++++++++++++++++++ AFL/alloc-inl.h | 577 +++++ AFL/config.h | 357 +++ AFL/debug.h | 258 ++ AFL/hash.h | 111 + AFL/types.h | 94 + 8 files changed, 8777 insertions(+) create mode 100755 AFL/Makefile create mode 100755 AFL/afl-as.h create mode 100755 AFL/afl-fuzz.c create mode 100755 AFL/alloc-inl.h create mode 100755 AFL/config.h create mode 100755 AFL/debug.h create mode 100755 AFL/hash.h create mode 100755 AFL/types.h diff --git a/AFL/Makefile b/AFL/Makefile new file mode 100755 index 0000000..64dca1d --- /dev/null +++ b/AFL/Makefile @@ -0,0 +1,47 @@ +# +# american fuzzy lop - makefile +# ----------------------------- +# +# Written and maintained by Michal Zalewski +# +# Copyright 2013, 2014, 2015, 2016, 2017 Google LLC All rights reserved. +# +# 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 +# + +PROGNAME = afl +VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2) + +#PGSQL_INSTALL_PATH = /mnt/raidhhd/postgrebin_no_instru# Replace with your own path +PGSQL_LIB_PATH = /home/wx/openGauss-server/inst_build/lib +PGSQL_INCLUDE_PATH = /home/wx/openGauss-server/inst_build/include +PREFIX ?= /usr/local +BIN_PATH = $(PREFIX)/bin +HELPER_PATH = $(PREFIX)/lib/afl +DOC_PATH = $(PREFIX)/share/doc/afl +MISC_PATH = $(PREFIX)/share/afl +DEPEN_PATH = ../src/*.cpp ../parser/bison_parser.cpp ../parser/flex_lexer.cpp + +# PROGS intentionally omit afl-as, which gets installed elsewhere. + +PROGS = afl-fuzz + +CC = g++ +CFLAGS ?= -fpermissive --std=c++17 #-fsanitize=address +CFLAGS += -g -w \ + -DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \ + -DBIN_PATH=\"$(BIN_PATH)\" + +COMM_HDR = alloc-inl.h config.h debug.h types.h + +all: $(PROGS) + +afl-fuzz: afl-fuzz.c $(COMM_HDR) + $(CC) $(CFLAGS) -I$(PGSQL_INCLUDE_PATH) -L$(PGSQL_LIB_PATH) -g $@.c $(DEPEN_PATH) -o $@ $(LDFLAGS) -ldl -lpq + +clean: + rm -f afl-fuzz diff --git a/AFL/afl-as.h b/AFL/afl-as.h new file mode 100755 index 0000000..276b8a4 --- /dev/null +++ b/AFL/afl-as.h @@ -0,0 +1,727 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - injectable parts + ------------------------------------- + + Written and maintained by Michal Zalewski + + Forkserver design by Jann Horn + + This file houses the assembly-level instrumentation injected into fuzzed + programs. The instrumentation stores XORed pairs of data: identifiers of the + currently executing branch and the one that executed immediately before. + + TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++ + + The code is designed for 32-bit and 64-bit x86 systems. Both modes should + work everywhere except for Apple systems. Apple does relocations differently + from everybody else, so since their OSes have been 64-bit for a longer while, + I didn't go through the mental effort of porting the 32-bit code. + + In principle, similar code should be easy to inject into any well-behaved + binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural + targets for instrumentation, and should offer comparable probe density. + +*/ + +#ifndef _HAVE_AFL_AS_H +#define _HAVE_AFL_AS_H + +#include "config.h" +#include "types.h" + +/* + ------------------ + Performances notes + ------------------ + + Contributions to make this code faster are appreciated! Here are some + rough notes that may help with the task: + + - Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are + really worth optimizing; the setup / fork server stuff matters a lot less + and should be mostly just kept readable. + + - We're aiming for modern CPUs with out-of-order execution and large + pipelines; the code is mostly follows intuitive, human-readable + instruction ordering, because "textbook" manual reorderings make no + substantial difference. + + - Interestingly, instrumented execution isn't a lot faster if we store a + variable pointer to the setup, log, or return routine and then do a reg + call from within trampoline_fmt. It does speed up non-instrumented + execution quite a bit, though, since that path just becomes + push-call-ret-pop. + + - There is also not a whole lot to be gained by doing SHM attach at a + fixed address instead of retrieving __afl_area_ptr. Although it allows us + to have a shorter log routine inserted for conditional jumps and jump + labels (for a ~10% perf gain), there is a risk of bumping into other + allocations created by the program or by tools such as ASAN. + + - popf is *awfully* slow, which is why we're doing the lahf / sahf + + overflow test trick. Unfortunately, this forces us to taint eax / rax, but + this dependency on a commonly-used register still beats the alternative of + using pushf / popf. + + One possible optimization is to avoid touching flags by using a circular + buffer that stores just a sequence of current locations, with the XOR stuff + happening offline. Alas, this doesn't seem to have a huge impact: + + https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ + + - Preforking one child a bit sooner, and then waiting for the "go" command + from within the child, doesn't offer major performance gains; fork() seems + to be relatively inexpensive these days. Preforking multiple children does + help, but badly breaks the "~1 core per fuzzer" design, making it harder to + scale up. Maybe there is some middle ground. + + Perhaps of note: in the 64-bit version for all platforms except for Apple, + the instrumentation is done slightly differently than on 32-bit, with + __afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm), + rather than global (.comm). This is to avoid GOTRELPC lookups in the critical + code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to + work; simple relocations between .bss and .text won't work on most 64-bit + platforms in such a case. + + (Fun fact: on Apple systems, .lcomm can segfault the linker.) + + The side effect is that state transitions are measured in a somewhat + different way, with previous tuple being recorded separately within the scope + of every .c file. This should have no impact in any practical sense. + + Another side effect of this design is that getenv() will be called once per + every .o file when running in non-instrumented mode; and since getenv() tends + to be optimized in funny ways, we need to be very careful to save every + oddball register it may touch. + + */ + +static const u8* trampoline_fmt_32 = + + "\n" + "/* --- AFL TRAMPOLINE (32-BIT) --- */\n" + "\n" + ".align 4\n" + "\n" + "leal -16(%%esp), %%esp\n" + "movl %%edi, 0(%%esp)\n" + "movl %%edx, 4(%%esp)\n" + "movl %%ecx, 8(%%esp)\n" + "movl %%eax, 12(%%esp)\n" + "movl $0x%08x, %%ecx\n" + "call __afl_maybe_log\n" + "movl 12(%%esp), %%eax\n" + "movl 8(%%esp), %%ecx\n" + "movl 4(%%esp), %%edx\n" + "movl 0(%%esp), %%edi\n" + "leal 16(%%esp), %%esp\n" + "\n" + "/* --- END --- */\n" + "\n"; + +static const u8* trampoline_fmt_64 = + + "\n" + "/* --- AFL TRAMPOLINE (64-BIT) --- */\n" + "\n" + ".align 4\n" + "\n" + "leaq -(128+24)(%%rsp), %%rsp\n" + "movq %%rdx, 0(%%rsp)\n" + "movq %%rcx, 8(%%rsp)\n" + "movq %%rax, 16(%%rsp)\n" + "movq $0x%08x, %%rcx\n" + "call __afl_maybe_log\n" + "movq 16(%%rsp), %%rax\n" + "movq 8(%%rsp), %%rcx\n" + "movq 0(%%rsp), %%rdx\n" + "leaq (128+24)(%%rsp), %%rsp\n" + "\n" + "/* --- END --- */\n" + "\n"; + +static const u8* main_payload_32 = + + "\n" + "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n" + "\n" + ".text\n" + ".att_syntax\n" + ".code32\n" + ".align 8\n" + "\n" + + "__afl_maybe_log:\n" + "\n" + " lahf\n" + " seto %al\n" + "\n" + " /* Check if SHM region is already mapped. */\n" + "\n" + " movl __afl_area_ptr, %edx\n" + " testl %edx, %edx\n" + " je __afl_setup\n" + "\n" + "__afl_store:\n" + "\n" + " /* Calculate and store hit for the code location specified in ecx. There\n" + " is a double-XOR way of doing this without tainting another register,\n" + " and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n" + "\n" +#ifndef COVERAGE_ONLY + " movl __afl_prev_loc, %edi\n" + " xorl %ecx, %edi\n" + " shrl $1, %ecx\n" + " movl %ecx, __afl_prev_loc\n" +#else + " movl %ecx, %edi\n" +#endif /* ^!COVERAGE_ONLY */ + "\n" +#ifdef SKIP_COUNTS + " orb $1, (%edx, %edi, 1)\n" +#else + " incb (%edx, %edi, 1)\n" +#endif /* ^SKIP_COUNTS */ + "\n" + "__afl_return:\n" + "\n" + " addb $127, %al\n" + " sahf\n" + " ret\n" + "\n" + ".align 8\n" + "\n" + "__afl_setup:\n" + "\n" + " /* Do not retry setup if we had previous failures. */\n" + "\n" + " cmpb $0, __afl_setup_failure\n" + " jne __afl_return\n" + "\n" + " /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n" + " We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n" + " will notice this early in the game. */\n" + "\n" + " pushl %eax\n" + " pushl %ecx\n" + "\n" + " pushl $.AFL_SHM_ENV\n" + " call getenv\n" + " addl $4, %esp\n" + "\n" + " testl %eax, %eax\n" + " je __afl_setup_abort\n" + "\n" + " pushl %eax\n" + " call atoi\n" + " addl $4, %esp\n" + "\n" + " pushl $0 /* shmat flags */\n" + " pushl $0 /* requested addr */\n" + " pushl %eax /* SHM ID */\n" + " call shmat\n" + " addl $12, %esp\n" + "\n" + " cmpl $-1, %eax\n" + " je __afl_setup_abort\n" + "\n" + " /* Store the address of the SHM region. */\n" + "\n" + " movl %eax, __afl_area_ptr\n" + " movl %eax, %edx\n" + "\n" + " popl %ecx\n" + " popl %eax\n" + "\n" + "__afl_forkserver:\n" + "\n" + " /* Enter the fork server mode to avoid the overhead of execve() calls. */\n" + "\n" + " pushl %eax\n" + " pushl %ecx\n" + " pushl %edx\n" + "\n" + " /* Phone home and tell the parent that we're OK. (Note that signals with\n" + " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" + " closed because we were execve()d from an instrumented binary, or because\n" + " the parent doesn't want to use the fork server. */\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_temp /* data */\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" + " call write\n" + " addl $12, %esp\n" + "\n" + " cmpl $4, %eax\n" + " jne __afl_fork_resume\n" + "\n" + "__afl_fork_wait_loop:\n" + "\n" + " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_temp /* data */\n" + " pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n" + " call read\n" + " addl $12, %esp\n" + "\n" + " cmpl $4, %eax\n" + " jne __afl_die\n" + "\n" + " /* Once woken up, create a clone of our process. This is an excellent use\n" + " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" + " caches getpid() results and offers no way to update the value, breaking\n" + " abort(), raise(), and a bunch of other things :-( */\n" + "\n" + " call fork\n" + "\n" + " cmpl $0, %eax\n" + " jl __afl_die\n" + " je __afl_fork_resume\n" + "\n" + " /* In parent process: write PID to pipe, then wait for child. */\n" + "\n" + " movl %eax, __afl_fork_pid\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_fork_pid /* data */\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" + " call write\n" + " addl $12, %esp\n" + "\n" + " pushl $0 /* no flags */\n" + " pushl $__afl_temp /* status */\n" + " pushl __afl_fork_pid /* PID */\n" + " call waitpid\n" + " addl $12, %esp\n" + "\n" + " cmpl $0, %eax\n" + " jle __afl_die\n" + "\n" + " /* Relay wait status to pipe, then loop back. */\n" + "\n" + " pushl $4 /* length */\n" + " pushl $__afl_temp /* data */\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n" + " call write\n" + " addl $12, %esp\n" + "\n" + " jmp __afl_fork_wait_loop\n" + "\n" + "__afl_fork_resume:\n" + "\n" + " /* In child process: close fds, resume execution. */\n" + "\n" + " pushl $" STRINGIFY(FORKSRV_FD) "\n" + " call close\n" + "\n" + " pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n" + " call close\n" + "\n" + " addl $8, %esp\n" + "\n" + " popl %edx\n" + " popl %ecx\n" + " popl %eax\n" + " jmp __afl_store\n" + "\n" + "__afl_die:\n" + "\n" + " xorl %eax, %eax\n" + " call _exit\n" + "\n" + "__afl_setup_abort:\n" + "\n" + " /* Record setup failure so that we don't keep calling\n" + " shmget() / shmat() over and over again. */\n" + "\n" + " incb __afl_setup_failure\n" + " popl %ecx\n" + " popl %eax\n" + " jmp __afl_return\n" + "\n" + ".AFL_VARS:\n" + "\n" + " .comm __afl_area_ptr, 4, 32\n" + " .comm __afl_setup_failure, 1, 32\n" +#ifndef COVERAGE_ONLY + " .comm __afl_prev_loc, 4, 32\n" +#endif /* !COVERAGE_ONLY */ + " .comm __afl_fork_pid, 4, 32\n" + " .comm __afl_temp, 4, 32\n" + "\n" + ".AFL_SHM_ENV:\n" + " .asciz \"" SHM_ENV_VAR "\"\n" + "\n" + "/* --- END --- */\n" + "\n"; + +/* The OpenBSD hack is due to lahf and sahf not being recognized by some + versions of binutils: http://marc.info/?l=openbsd-cvs&m=141636589924400 + + The Apple code is a bit different when calling libc functions because + they are doing relocations differently from everybody else. We also need + to work around the crash issue with .lcomm and the fact that they don't + recognize .string. */ + +#ifdef __APPLE__ +# define CALL_L64(str) "call _" str "\n" +#else +# define CALL_L64(str) "call " str "@PLT\n" +#endif /* ^__APPLE__ */ + +static const u8* main_payload_64 = + + "\n" + "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n" + "\n" + ".text\n" + ".att_syntax\n" + ".code64\n" + ".align 8\n" + "\n" + "__afl_maybe_log:\n" + "\n" +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) + " .byte 0x9f /* lahf */\n" +#else + " lahf\n" +#endif /* ^__OpenBSD__, etc */ + " seto %al\n" + "\n" + " /* Check if SHM region is already mapped. */\n" + "\n" + " movq __afl_area_ptr(%rip), %rdx\n" + " testq %rdx, %rdx\n" + " je __afl_setup\n" + "\n" + "__afl_store:\n" + "\n" + " /* Calculate and store hit for the code location specified in rcx. */\n" + "\n" +#ifndef COVERAGE_ONLY + " xorq __afl_prev_loc(%rip), %rcx\n" + " xorq %rcx, __afl_prev_loc(%rip)\n" + " shrq $1, __afl_prev_loc(%rip)\n" +#endif /* ^!COVERAGE_ONLY */ + "\n" +#ifdef SKIP_COUNTS + " orb $1, (%rdx, %rcx, 1)\n" +#else + " incb (%rdx, %rcx, 1)\n" +#endif /* ^SKIP_COUNTS */ + "\n" + "__afl_return:\n" + "\n" + " addb $127, %al\n" +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) + " .byte 0x9e /* sahf */\n" +#else + " sahf\n" +#endif /* ^__OpenBSD__, etc */ + " ret\n" + "\n" + ".align 8\n" + "\n" + "__afl_setup:\n" + "\n" + " /* Do not retry setup if we had previous failures. */\n" + "\n" + " cmpb $0, __afl_setup_failure(%rip)\n" + " jne __afl_return\n" + "\n" + " /* Check out if we have a global pointer on file. */\n" + "\n" +#ifndef __APPLE__ + " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" + " movq (%rdx), %rdx\n" +#else + " movq __afl_global_area_ptr(%rip), %rdx\n" +#endif /* !^__APPLE__ */ + " testq %rdx, %rdx\n" + " je __afl_setup_first\n" + "\n" + " movq %rdx, __afl_area_ptr(%rip)\n" + " jmp __afl_store\n" + "\n" + "__afl_setup_first:\n" + "\n" + " /* Save everything that is not yet saved and that may be touched by\n" + " getenv() and several other libcalls we'll be relying on. */\n" + "\n" + " leaq -352(%rsp), %rsp\n" + "\n" + " movq %rax, 0(%rsp)\n" + " movq %rcx, 8(%rsp)\n" + " movq %rdi, 16(%rsp)\n" + " movq %rsi, 32(%rsp)\n" + " movq %r8, 40(%rsp)\n" + " movq %r9, 48(%rsp)\n" + " movq %r10, 56(%rsp)\n" + " movq %r11, 64(%rsp)\n" + "\n" + " movq %xmm0, 96(%rsp)\n" + " movq %xmm1, 112(%rsp)\n" + " movq %xmm2, 128(%rsp)\n" + " movq %xmm3, 144(%rsp)\n" + " movq %xmm4, 160(%rsp)\n" + " movq %xmm5, 176(%rsp)\n" + " movq %xmm6, 192(%rsp)\n" + " movq %xmm7, 208(%rsp)\n" + " movq %xmm8, 224(%rsp)\n" + " movq %xmm9, 240(%rsp)\n" + " movq %xmm10, 256(%rsp)\n" + " movq %xmm11, 272(%rsp)\n" + " movq %xmm12, 288(%rsp)\n" + " movq %xmm13, 304(%rsp)\n" + " movq %xmm14, 320(%rsp)\n" + " movq %xmm15, 336(%rsp)\n" + "\n" + " /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n" + "\n" + " /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n" + " original stack ptr in the callee-saved r12. */\n" + "\n" + " pushq %r12\n" + " movq %rsp, %r12\n" + " subq $16, %rsp\n" + " andq $0xfffffffffffffff0, %rsp\n" + "\n" + " leaq .AFL_SHM_ENV(%rip), %rdi\n" + CALL_L64("getenv") + "\n" + " testq %rax, %rax\n" + " je __afl_setup_abort\n" + "\n" + " movq %rax, %rdi\n" + CALL_L64("atoi") + "\n" + " xorq %rdx, %rdx /* shmat flags */\n" + " xorq %rsi, %rsi /* requested addr */\n" + " movq %rax, %rdi /* SHM ID */\n" + CALL_L64("shmat") + "\n" + " cmpq $-1, %rax\n" + " je __afl_setup_abort\n" + "\n" + " /* Store the address of the SHM region. */\n" + "\n" + " movq %rax, %rdx\n" + " movq %rax, __afl_area_ptr(%rip)\n" + "\n" +#ifdef __APPLE__ + " movq %rax, __afl_global_area_ptr(%rip)\n" +#else + " movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" + " movq %rax, (%rdx)\n" +#endif /* ^__APPLE__ */ + " movq %rax, %rdx\n" + "\n" + "__afl_forkserver:\n" + "\n" + " /* Enter the fork server mode to avoid the overhead of execve() calls. We\n" + " push rdx (area ptr) twice to keep stack alignment neat. */\n" + "\n" + " pushq %rdx\n" + " pushq %rdx\n" + "\n" + " /* Phone home and tell the parent that we're OK. (Note that signals with\n" + " no SA_RESTART will mess it up). If this fails, assume that the fd is\n" + " closed because we were execve()d from an instrumented binary, or because\n" + " the parent doesn't want to use the fork server. */\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_temp(%rip), %rsi /* data */\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" + CALL_L64("write") + "\n" + " cmpq $4, %rax\n" + " jne __afl_fork_resume\n" + "\n" + "__afl_fork_wait_loop:\n" + "\n" + " /* Wait for parent by reading from the pipe. Abort if read fails. */\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_temp(%rip), %rsi /* data */\n" + " movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n" + CALL_L64("read") + " cmpq $4, %rax\n" + " jne __afl_die\n" + "\n" + " /* Once woken up, create a clone of our process. This is an excellent use\n" + " case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" + " caches getpid() results and offers no way to update the value, breaking\n" + " abort(), raise(), and a bunch of other things :-( */\n" + "\n" + CALL_L64("fork") + " cmpq $0, %rax\n" + " jl __afl_die\n" + " je __afl_fork_resume\n" + "\n" + " /* In parent process: write PID to pipe, then wait for child. */\n" + "\n" + " movl %eax, __afl_fork_pid(%rip)\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_fork_pid(%rip), %rsi /* data */\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" + CALL_L64("write") + "\n" + " movq $0, %rdx /* no flags */\n" + " leaq __afl_temp(%rip), %rsi /* status */\n" + " movq __afl_fork_pid(%rip), %rdi /* PID */\n" + CALL_L64("waitpid") + " cmpq $0, %rax\n" + " jle __afl_die\n" + "\n" + " /* Relay wait status to pipe, then loop back. */\n" + "\n" + " movq $4, %rdx /* length */\n" + " leaq __afl_temp(%rip), %rsi /* data */\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n" + CALL_L64("write") + "\n" + " jmp __afl_fork_wait_loop\n" + "\n" + "__afl_fork_resume:\n" + "\n" + " /* In child process: close fds, resume execution. */\n" + "\n" + " movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n" + CALL_L64("close") + "\n" + " movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n" + CALL_L64("close") + "\n" + " popq %rdx\n" + " popq %rdx\n" + "\n" + " movq %r12, %rsp\n" + " popq %r12\n" + "\n" + " movq 0(%rsp), %rax\n" + " movq 8(%rsp), %rcx\n" + " movq 16(%rsp), %rdi\n" + " movq 32(%rsp), %rsi\n" + " movq 40(%rsp), %r8\n" + " movq 48(%rsp), %r9\n" + " movq 56(%rsp), %r10\n" + " movq 64(%rsp), %r11\n" + "\n" + " movq 96(%rsp), %xmm0\n" + " movq 112(%rsp), %xmm1\n" + " movq 128(%rsp), %xmm2\n" + " movq 144(%rsp), %xmm3\n" + " movq 160(%rsp), %xmm4\n" + " movq 176(%rsp), %xmm5\n" + " movq 192(%rsp), %xmm6\n" + " movq 208(%rsp), %xmm7\n" + " movq 224(%rsp), %xmm8\n" + " movq 240(%rsp), %xmm9\n" + " movq 256(%rsp), %xmm10\n" + " movq 272(%rsp), %xmm11\n" + " movq 288(%rsp), %xmm12\n" + " movq 304(%rsp), %xmm13\n" + " movq 320(%rsp), %xmm14\n" + " movq 336(%rsp), %xmm15\n" + "\n" + " leaq 352(%rsp), %rsp\n" + "\n" + " jmp __afl_store\n" + "\n" + "__afl_die:\n" + "\n" + " xorq %rax, %rax\n" + CALL_L64("_exit") + "\n" + "__afl_setup_abort:\n" + "\n" + " /* Record setup failure so that we don't keep calling\n" + " shmget() / shmat() over and over again. */\n" + "\n" + " incb __afl_setup_failure(%rip)\n" + "\n" + " movq %r12, %rsp\n" + " popq %r12\n" + "\n" + " movq 0(%rsp), %rax\n" + " movq 8(%rsp), %rcx\n" + " movq 16(%rsp), %rdi\n" + " movq 32(%rsp), %rsi\n" + " movq 40(%rsp), %r8\n" + " movq 48(%rsp), %r9\n" + " movq 56(%rsp), %r10\n" + " movq 64(%rsp), %r11\n" + "\n" + " movq 96(%rsp), %xmm0\n" + " movq 112(%rsp), %xmm1\n" + " movq 128(%rsp), %xmm2\n" + " movq 144(%rsp), %xmm3\n" + " movq 160(%rsp), %xmm4\n" + " movq 176(%rsp), %xmm5\n" + " movq 192(%rsp), %xmm6\n" + " movq 208(%rsp), %xmm7\n" + " movq 224(%rsp), %xmm8\n" + " movq 240(%rsp), %xmm9\n" + " movq 256(%rsp), %xmm10\n" + " movq 272(%rsp), %xmm11\n" + " movq 288(%rsp), %xmm12\n" + " movq 304(%rsp), %xmm13\n" + " movq 320(%rsp), %xmm14\n" + " movq 336(%rsp), %xmm15\n" + "\n" + " leaq 352(%rsp), %rsp\n" + "\n" + " jmp __afl_return\n" + "\n" + ".AFL_VARS:\n" + "\n" + +#ifdef __APPLE__ + + " .comm __afl_area_ptr, 8\n" +#ifndef COVERAGE_ONLY + " .comm __afl_prev_loc, 8\n" +#endif /* !COVERAGE_ONLY */ + " .comm __afl_fork_pid, 4\n" + " .comm __afl_temp, 4\n" + " .comm __afl_setup_failure, 1\n" + +#else + + " .lcomm __afl_area_ptr, 8\n" +#ifndef COVERAGE_ONLY + " .lcomm __afl_prev_loc, 8\n" +#endif /* !COVERAGE_ONLY */ + " .lcomm __afl_fork_pid, 4\n" + " .lcomm __afl_temp, 4\n" + " .lcomm __afl_setup_failure, 1\n" + +#endif /* ^__APPLE__ */ + + " .comm __afl_global_area_ptr, 8, 8\n" + "\n" + ".AFL_SHM_ENV:\n" + " .asciz \"" SHM_ENV_VAR "\"\n" + "\n" + "/* --- END --- */\n" + "\n"; + +#endif /* !_HAVE_AFL_AS_H */ diff --git a/AFL/afl-fuzz.c b/AFL/afl-fuzz.c new file mode 100755 index 0000000..c024cb2 --- /dev/null +++ b/AFL/afl-fuzz.c @@ -0,0 +1,6606 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - fuzzer code + -------------------------------- + + Written and maintained by Michal Zalewski + + Forkserver design by Jann Horn + + This is the real deal: the program takes an instrumented binary and + attempts a variety of basic fuzzing tricks, paying close attention to + how they affect the execution path. + +*/ + +#define AFL_MAIN +#define MESSAGES_TO_STDOUT + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#define _FILE_OFFSET_BITS 64 + +#include "config.h" +#include "types.h" +#include "debug.h" +#include "alloc-inl.h" +#include "hash.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../include/ast.h" +#include "../include/mutate.h" +#include "../include//instantiate.h" +#include "../include/define.h" +#include "../include/connector.h" + +using namespace std; +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) +# include +#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ + +/* For systems that have sched_setaffinity; right now just Linux, but one + can hope... */ + +#ifdef __linux__ +# define HAVE_AFFINITY 1 +#endif /* __linux__ */ + +/* A toggle to export some variables when building as a library. Not very + useful for the general public. */ + +#ifdef AFL_LIB +# define EXP_ST +#else +# define EXP_ST static +#endif /* ^AFL_LIB */ + +/* Lots of globals, but mostly for the status UI and other things where it + really makes no sense to haul them around as function parameters. */ + +#define ABPATH "/home/omm/openGauss_Fuzzer_release/" +#define RLPATH_LIB "/corpus/initlib" +#define RLPATH_IRINFO "/corpus/IR_config" +#define RLPATH_OUTPUT "/" + +#define INIT_LIB ABPATH RLPATH_LIB +#define GRAMMAR_INFORMATION ABPATH RLPATH_IRINFO +#define OUTPUT_PATH ABPATH RLPATH_OUTPUT + +#define HOST "localhost" +#define USERNAME "omm" +#define PASSWORD "Aa1!@#$%^&*()" +#define PORT 5432 + +#define SERVERNAME "gaussdb" +const char* file = "/home/wx/openGauss-server/inst_build/bin/gs_ctl"; +char* const options[] = { "/home/wx/openGauss-server/inst_build/bin/gs_ctl", "start", "-D", "/home/omm/data", "-Z", "single_node", "-l", "/home/omm/log/opengauss.log", NULL }; + +static long seed_count = 0; + +char* g_current_sql = nullptr; +InputInfo* g_current_input = nullptr; + +Mutator g_mutator; +Instantiator g_instantiator; +Connector g_connector(HOST, USERNAME, PASSWORD, PORT, SERVERNAME); + +EXP_ST u8 vaild_flag = 0; +EXP_ST u64 total_vaild = 0; + +EXP_ST u8 *in_dir, /* Input directory with test cases */ + *out_file, /* File to fuzz, if any */ + *out_dir, /* Working & output directory */ + *sync_dir, /* Synchronization directory */ + *sync_id, /* Fuzzer ID */ + *use_banner, /* Display banner */ + *in_bitmap, /* Input bitmap */ + *doc_path, /* Path to documentation dir */ + *target_path, /* Path to target binary */ + *orig_cmdline; /* Original command line */ + +EXP_ST u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */ +static u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */ + +EXP_ST u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */ + +static u32 stats_update_freq = 1; /* Stats update frequency (execs) */ + +EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */ + force_deterministic, /* Force deterministic stages? */ + use_splicing, /* Recombine input files? */ + dumb_mode, /* Run in non-instrumented mode? */ + score_changed, /* Scoring for favorites changed? */ + kill_signal, /* Signal that killed the child */ + resuming_fuzz, /* Resuming an older fuzzing job? */ + timeout_given, /* Specific timeout given? */ + not_on_tty, /* stdout is not a tty */ + term_too_small, /* terminal dimensions too small */ + uses_asan, /* Target uses ASAN? */ + no_forkserver, /* Disable forkserver? */ + crash_mode, /* Crash mode! Yeah! */ + in_place_resume, /* Attempt in-place resume? */ + auto_changed, /* Auto-generated tokens changed? */ + no_cpu_meter_red, /* Feng shui on the status screen */ + no_arith, /* Skip most arithmetic ops */ + shuffle_queue, /* Shuffle input queue? */ + bitmap_changed = 1, /* Time to update bitmap? */ + qemu_mode, /* Running in QEMU mode? */ + skip_requested, /* Skip request, via SIGUSR1 */ + run_over10m, /* Run time over 10 minutes? */ + persistent_mode, /* Running in persistent mode? */ + deferred_mode, /* Deferred forkserver mode? */ + fast_cal; /* Try to calibrate faster? */ + +static s32 out_fd, /* Persistent fd for out_file */ + dev_urandom_fd = -1, /* Persistent fd for /dev/urandom */ + dev_null_fd = -1, /* Persistent fd for /dev/null */ + fsrv_ctl_fd, /* Fork server control pipe (write) */ + fsrv_st_fd; /* Fork server status pipe (read) */ + +static s32 forksrv_pid, /* PID of the fork server */ + child_pid = -1, /* PID of the fuzzed program */ + out_dir_fd = -1; /* FD of the lock file */ + +EXP_ST u8* trace_bits; /* SHM with instrumentation bitmap */ + +EXP_ST u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ + virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ + virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */ + +static u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ + +static s32 shm_id; /* ID of the SHM region */ + +static volatile u8 stop_soon, /* Ctrl-C pressed? */ + clear_screen = 1, /* Window resized? */ + child_timed_out; /* Traced process timed out? */ + +EXP_ST u32 queued_paths, /* Total number of queued testcases */ + queued_variable, /* Testcases with variable behavior */ + queued_at_start, /* Total number of initial inputs */ + queued_discovered, /* Items discovered during this run */ + queued_imported, /* Items imported via -S */ + queued_favored, /* Paths deemed favorable */ + queued_with_cov, /* Paths with new coverage bytes */ + pending_not_fuzzed, /* Queued but not done yet */ + pending_favored, /* Pending favored paths */ + cur_skipped_paths, /* Abandoned inputs in cur cycle */ + cur_depth, /* Current path depth */ + max_depth, /* Max path depth */ + useless_at_start, /* Number of useless starting paths */ + var_byte_count, /* Bitmap bytes with var behavior */ + current_entry, /* Current queue entry ID */ + havoc_div = 1; /* Cycle count divisor for havoc */ + +EXP_ST u64 total_crashes, /* Total number of crashes */ + unique_crashes, /* Crashes with unique signatures */ + total_tmouts, /* Total number of timeouts */ + unique_tmouts, /* Timeouts with unique signatures */ + unique_hangs, /* Hangs with unique signatures */ + total_execs, /* Total execve() calls */ + cur_execs, + slowest_exec_ms, /* Slowest testcase non hang in ms */ + start_time, /* Unix start time (ms) */ + last_save_time, + last_path_time, /* Time for most recent path (ms) */ + last_crash_time, /* Time for most recent crash (ms) */ + last_hang_time, /* Time for most recent hang (ms) */ + last_crash_execs, /* Exec counter at last crash */ + queue_cycle, /* Queue round counter */ + cycles_wo_finds, /* Cycles without any new paths */ + trim_execs, /* Execs done to trim input files */ + bytes_trim_in, /* Bytes coming into the trimmer */ + bytes_trim_out, /* Bytes coming outa the trimmer */ + blocks_eff_total, /* Blocks subject to effector maps */ + blocks_eff_select; /* Blocks selected as fuzzable */ + +static u32 subseq_tmouts; /* Number of timeouts in a row */ + +static u8 *stage_name = "init", /* Name of the current fuzz stage */ + *stage_short, /* Short stage name */ + *syncing_party; /* Currently syncing with... */ + +static s32 stage_cur, stage_max; /* Stage progression */ +static s32 splicing_with = -1; /* Splicing with which test case? */ + +static u32 master_id, master_max; /* Master instance job splitting */ + +static u32 syncing_case; /* Syncing with case #... */ + +static s32 stage_cur_byte, /* Byte offset of current stage op */ + stage_cur_val; /* Value used for stage op */ + +static u8 stage_val_type; /* Value type (STAGE_VAL_*) */ + +static u64 stage_finds[32], /* Patterns found per fuzz stage */ + stage_cycles[32]; /* Execs per fuzz stage */ + +static u32 rand_cnt; /* Random number counter */ + +static u64 total_cal_us, /* Total calibration time (us) */ + total_cal_cycles = 1; /* Total calibration cycles */ + +static u64 total_bitmap_size, /* Total bit count for all bitmaps */ + total_bitmap_entries; /* Number of bitmaps counted */ + +static s32 cpu_core_count; /* CPU core count */ + +#ifdef HAVE_AFFINITY + +static s32 cpu_aff = -1; /* Selected CPU core */ + +#endif /* HAVE_AFFINITY */ + +static FILE* plot_file; /* Gnuplot output file */ + +struct queue_entry { + + u8* fname; /* File name for the test case */ + u32 len; /* Input length */ + + u8 cal_failed, /* Calibration failed? */ + trim_done, /* Trimmed? */ + was_fuzzed, /* Had any fuzzing done yet? */ + passed_det, /* Deterministic stages passed? */ + has_new_cov, /* Triggers new coverage? */ + var_behavior, /* Variable behavior? */ + favored, /* Currently favored? */ + fs_redundant; /* Marked as redundant in the fs? */ + + u32 bitmap_size, /* Number of bits set in bitmap */ + exec_cksum; /* Checksum of the execution trace */ + + u64 exec_us, /* Execution time (us) */ + handicap, /* Number of queue cycles behind */ + depth; /* Path depth */ + + u8* trace_mini; /* Trace bytes, if kept */ + u32 tc_ref; /* Trace bytes ref count */ + + struct queue_entry *next, /* Next element, if any */ + *next_100; /* 100 elements ahead */ + +}; + + +static struct queue_entry *queue, /* Fuzzing queue (linked list) */ + *queue_cur, /* Current offset within the queue */ + *queue_top, /* Top of the list */ + *q_prev100; /* Previous 100 marker */ + +static struct queue_entry* + top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */ + +struct extra_data { + u8* data; /* Dictionary token data */ + u32 len; /* Dictionary token length */ + u32 hit_cnt; /* Use count in the corpus */ +}; + +static struct extra_data* extras; /* Extra tokens to fuzz with */ +static u32 extras_cnt; /* Total number of tokens read */ + +static struct extra_data* a_extras; /* Automatically selected extras */ +static u32 a_extras_cnt; /* Total number of tokens available */ + +static u8* (*post_handler)(u8* buf, u32* len); + +/* Interesting values, as per config.h */ + +static s8 interesting_8[] = { INTERESTING_8 }; +static s16 interesting_16[] = { INTERESTING_8, INTERESTING_16 }; +static s32 interesting_32[] = { INTERESTING_8, INTERESTING_16, INTERESTING_32 }; + +/* Fuzzing stages */ + +enum { + /* 00 */ STAGE_FLIP1, + /* 01 */ STAGE_FLIP2, + /* 02 */ STAGE_FLIP4, + /* 03 */ STAGE_FLIP8, + /* 04 */ STAGE_FLIP16, + /* 05 */ STAGE_FLIP32, + /* 06 */ STAGE_ARITH8, + /* 07 */ STAGE_ARITH16, + /* 08 */ STAGE_ARITH32, + /* 09 */ STAGE_INTEREST8, + /* 10 */ STAGE_INTEREST16, + /* 11 */ STAGE_INTEREST32, + /* 12 */ STAGE_EXTRAS_UO, + /* 13 */ STAGE_EXTRAS_UI, + /* 14 */ STAGE_EXTRAS_AO, + /* 15 */ STAGE_HAVOC, + /* 16 */ STAGE_SPLICE +}; + +/* Stage value types */ + +enum { + /* 00 */ STAGE_VAL_NONE, + /* 01 */ STAGE_VAL_LE, + /* 02 */ STAGE_VAL_BE +}; + +/* Execution status fault codes */ + +enum { + /* 00 */ FAULT_NONE, + /* 01 */ FAULT_TMOUT, + /* 02 */ FAULT_CRASH, + /* 03 */ FAULT_ERROR, + /* 04 */ FAULT_NOINST, + /* 05 */ FAULT_NOBITS +}; + + +/* Get unix time in milliseconds */ +static u64 get_cur_time(void) { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); + +} + +/* Get unix time in microseconds */ + +static u64 get_cur_time_us(void) { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return (tv.tv_sec * 1000000ULL) + tv.tv_usec; + +} + + +/* Generate a random number (from 0 to limit - 1). This may + have slight bias. */ + +static inline u32 UR(u32 limit) { + + if (unlikely(!rand_cnt--)) { + + u32 seed[2]; + + ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom"); + + srandom(seed[0]); + rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG); + + } + + return random() % limit; + +} + + +/* Shuffle an array of pointers. Might be slightly biased. */ + +static void shuffle_ptrs(void** ptrs, u32 cnt) { + + u32 i; + + for (i = 0; i < cnt - 2; i++) { + + u32 j = i + UR(cnt - i); + void *s = ptrs[i]; + ptrs[i] = ptrs[j]; + ptrs[j] = s; + + } + +} + + +#ifdef HAVE_AFFINITY + +/* Build a list of processes bound to specific cores. Returns -1 if nothing + can be found. Assumes an upper bound of 4k CPUs. */ + +static void bind_to_free_cpu(void) { + + DIR* d; + struct dirent* de; + cpu_set_t c; + + u8 cpu_used[4096] = { 0 }; + u32 i; + + if (cpu_core_count < 2) return; + + if (getenv("AFL_NO_AFFINITY")) { + + WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set)."); + return; + + } + + d = opendir("/proc"); + + if (!d) { + + WARNF("Unable to access /proc - can't scan for free CPU cores."); + return; + + } + + ACTF("Checking CPU core loadout..."); + + /* Introduce some jitter, in case multiple AFL tasks are doing the same + thing at the same time... */ + + usleep(R(1000) * 250); + + /* Scan all /proc//status entries, checking for Cpus_allowed_list. + Flag all processes bound to a specific CPU using cpu_used[]. This will + fail for some exotic binding setups, but is likely good enough in almost + all real-world use cases. */ + + while ((de = readdir(d))) { + + u8* fn; + FILE* f; + u8 tmp[MAX_LINE]; + u8 has_vmsize = 0; + + if (!isdigit(de->d_name[0])) continue; + + fn = alloc_printf("/proc/%s/status", de->d_name); + + if (!(f = fopen(fn, "r"))) { + ck_free(fn); + continue; + } + + while (fgets(tmp, MAX_LINE, f)) { + + u32 hval; + + /* Processes without VmSize are probably kernel tasks. */ + + if (!strncmp(tmp, "VmSize:\t", 8)) has_vmsize = 1; + + if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && + !strchr((char *)tmp, int('-')) && !strchr((char *)tmp, int(',')) && + sscanf(tmp + 19, "%u", &hval) == 1 && hval < sizeof(cpu_used) && + has_vmsize) { + + cpu_used[hval] = 1; + break; + + } + + } + + ck_free(fn); + fclose(f); + + } + + closedir(d); + + for (i = 0; i < cpu_core_count; i++) if (!cpu_used[i]) break; + + if (i == cpu_core_count) { + + SAYF("\n" cLRD "[-] " cRST + "Uh-oh, looks like all %u CPU cores on your system are allocated to\n" + " other instances of afl-fuzz (or similar CPU-locked tasks). Starting\n" + " another fuzzer on this machine is probably a bad plan, but if you are\n" + " absolutely sure, you can set AFL_NO_AFFINITY and try again.\n", + cpu_core_count); + + FATAL("No more free CPU cores"); + + } + + OKF("Found a free CPU core, binding to #%u.", i); + + cpu_aff = i; + + CPU_ZERO(&c); + CPU_SET(i, &c); + + if (sched_setaffinity(0, sizeof(c), &c)) + PFATAL("sched_setaffinity failed"); + +} + +#endif /* HAVE_AFFINITY */ + +#ifndef IGNORE_FINDS + +/* Helper function to compare buffers; returns first and last differing offset. We + use this to find reasonable locations for splicing two files. */ + +static void locate_diffs(u8* ptr1, u8* ptr2, u32 len, s32* first, s32* last) { + + s32 f_loc = -1; + s32 l_loc = -1; + u32 pos; + + for (pos = 0; pos < len; pos++) { + + if (*(ptr1++) != *(ptr2++)) { + + if (f_loc == -1) f_loc = pos; + l_loc = pos; + + } + + } + + *first = f_loc; + *last = l_loc; + + return; + +} + +#endif /* !IGNORE_FINDS */ + + +/* Describe integer. Uses 12 cyclic static buffers for return values. The value + returned should be five characters or less for all the integers we reasonably + expect to see. */ + +static u8* DI(u64 val) { + + static u8 tmp[12][16]; + static u8 cur; + + cur = (cur + 1) % 12; + +#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) do { \ + if (val < (_divisor) * (_limit_mult)) { \ + sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \ + return tmp[cur]; \ + } \ + } while (0) + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1000, 99.95, "%0.01fk", double); + + /* 100k - 999k */ + CHK_FORMAT(1000, 1000, "%lluk", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); + + /* 100M - 999M */ + CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); + + /* 100G - 999G */ + CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); + + /* 100T+ */ + strcpy(tmp[cur], "infty"); + return tmp[cur]; + +} + + +/* Describe float. Similar to the above, except with a single + static buffer. */ + +static u8* DF(double val) { + + static u8 tmp[16]; + + if (val < 99.995) { + sprintf(tmp, "%0.02f", val); + return tmp; + } + + if (val < 999.95) { + sprintf(tmp, "%0.01f", val); + return tmp; + } + + return DI((u64)val); + +} + + +/* Describe integer as memory size. */ + +static u8* DMS(u64 val) { + + static u8 tmp[12][16]; + static u8 cur; + + cur = (cur + 1) % 12; + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu B", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1024, 99.95, "%0.01f kB", double); + + /* 100k - 999k */ + CHK_FORMAT(1024, 1000, "%llu kB", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); + + /* 100M - 999M */ + CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); + + /* 100G - 999G */ + CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); + +#undef CHK_FORMAT + + /* 100T+ */ + strcpy(tmp[cur], "infty"); + return tmp[cur]; + +} + + +/* Describe time delta. Returns one static buffer, 34 chars of less. */ + +static u8* DTD(u64 cur_ms, u64 event_ms) { + + static u8 tmp[64]; + u64 delta; + s32 t_d, t_h, t_m, t_s; + + if (!event_ms) return "none seen yet"; + + delta = cur_ms - event_ms; + + t_d = delta / 1000 / 60 / 60 / 24; + t_h = (delta / 1000 / 60 / 60) % 24; + t_m = (delta / 1000 / 60) % 60; + t_s = (delta / 1000) % 60; + + sprintf(tmp, "%s days, %u hrs, %u min, %u sec", DI(t_d), t_h, t_m, t_s); + return tmp; + +} + + +/* Mark deterministic checks as done for a particular queue entry. We use the + .state file to avoid repeating deterministic fuzzing when resuming aborted + scans. */ + +static void mark_as_det_done(struct queue_entry* q) { + + u8* fn = strrchr((const char*)q->fname, '/'); + s32 fd; + + fn = alloc_printf("%s/queue/.state/deterministic_done/%s", out_dir, fn + 1); + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + close(fd); + + ck_free(fn); + + q->passed_det = 1; + +} + + +/* Mark as variable. Create symlinks if possible to make it easier to examine + the files. */ + +static void mark_as_variable(struct queue_entry* q) { + + u8 *fn = strrchr((char *)q->fname, '/') + 1, *ldest; + + ldest = alloc_printf("../../%s", fn); + fn = alloc_printf("%s/queue/.state/variable_behavior/%s", out_dir, fn); + + if (symlink(ldest, fn)) { + + s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + close(fd); + + } + + ck_free(ldest); + ck_free(fn); + + q->var_behavior = 1; + +} + + +/* Mark / unmark as redundant (edge-only). This is not used for restoring state, + but may be useful for post-processing datasets. */ + +static void mark_as_redundant(struct queue_entry* q, u8 state) { + + u8* fn; + s32 fd; + + if (state == q->fs_redundant) return; + + q->fs_redundant = state; + + fn = strrchr((const char*)q->fname, '/'); + fn = alloc_printf("%s/queue/.state/redundant_edges/%s", out_dir, fn + 1); + + if (state) { + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + close(fd); + + } else { + + if (unlink(fn)) PFATAL("Unable to remove '%s'", fn); + + } + + ck_free(fn); + +} + + +/* Append new test case to the queue. */ + +static void add_to_queue(u8* fname, u32 len, u8 passed_det) { + + struct queue_entry* q = ck_alloc(sizeof(struct queue_entry)); + + q->fname = fname; + q->len = len; + q->depth = cur_depth + 1; + q->passed_det = passed_det; + + if (q->depth > max_depth) max_depth = q->depth; + + if (queue_top) { + + queue_top->next = q; + queue_top = q; + + } else q_prev100 = queue = queue_top = q; + + queued_paths++; + pending_not_fuzzed++; + + cycles_wo_finds = 0; + + if (!(queued_paths % 100)) { + + q_prev100->next_100 = q; + q_prev100 = q; + + } + + last_path_time = get_cur_time(); + +} + + +/* Destroy the entire queue. */ + +EXP_ST void destroy_queue(void) { + + struct queue_entry *q = queue, *n; + + while (q) { + + n = q->next; + ck_free(q->fname); + ck_free(q->trace_mini); + ck_free(q); + q = n; + + } + +} + + +/* Write bitmap to file. The bitmap is useful mostly for the secret + -B option, to focus a separate fuzzing session on a particular + interesting input without rediscovering all the others. */ + +EXP_ST void write_bitmap(void) { + + u8* fname; + s32 fd; + + if (!bitmap_changed) return; + bitmap_changed = 0; + + fname = alloc_printf("%s/fuzz_bitmap", out_dir); + fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to open '%s'", fname); + + ck_write(fd, virgin_bits, MAP_SIZE, fname); + + close(fd); + ck_free(fname); + +} + + +/* Read bitmap from file. This is for the -B option again. */ + +EXP_ST void read_bitmap(u8* fname) { + + s32 fd = open(fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", fname); + + ck_read(fd, virgin_bits, MAP_SIZE, fname); + + close(fd); + +} + + +/* Check if the current execution path brings anything new to the table. + Update virgin bits to reflect the finds. Returns 1 if the only change is + the hit-count for a particular tuple; 2 if there are new tuples seen. + Updates the map, so subsequent calls will always return 0. + + This function is called after every exec() on a fairly large buffer, so + it needs to be fast. We do this in 32-bit and 64-bit flavors. */ + +static inline u8 has_new_bits(u8* virgin_map) { + +#ifdef __x86_64__ + + u64* current = (u64*)trace_bits; + u64* virgin = (u64*)virgin_map; + + u32 i = (MAP_SIZE >> 3); + +#else + + u32* current = (u32*)trace_bits; + u32* virgin = (u32*)virgin_map; + + u32 i = (MAP_SIZE >> 2); + +#endif /* ^__x86_64__ */ + + u8 ret = 0; + + while (i--) { + + /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap + that have not been already cleared from the virgin map - since this will + almost always be the case. */ + + if (unlikely(*current) && unlikely(*current & *virgin)) { + + if (likely(ret < 2)) { + + u8* cur = (u8*)current; + u8* vir = (u8*)virgin; + + /* Looks like we have not found any new bytes yet; see if any non-zero + bytes in current[] are pristine in virgin[]. */ + +#ifdef __x86_64__ + + if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || + (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || + (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || + (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) ret = 2; + else ret = 1; + +#else + + if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || + (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) ret = 2; + else ret = 1; + +#endif /* ^__x86_64__ */ + + } + + *virgin &= ~*current; + + } + + current++; + virgin++; + + } + + if (ret && virgin_map == virgin_bits) bitmap_changed = 1; + + return ret; + +} + + +/* Count the number of bits set in the provided bitmap. Used for the status + screen several times every second, does not have to be fast. */ + +static u32 count_bits(u8* mem) { + + u32* ptr = (u32*)mem; + u32 i = (MAP_SIZE >> 2); + u32 ret = 0; + + while (i--) { + + u32 v = *(ptr++); + + /* This gets called on the inverse, virgin bitmap; optimize for sparse + data. */ + + if (v == 0xffffffff) { + ret += 32; + continue; + } + + v -= ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; + + } + + return ret; + +} + + +#define FF(_b) (0xff << ((_b) << 3)) + +/* Count the number of bytes set in the bitmap. Called fairly sporadically, + mostly to update the status screen or calibrate and examine confirmed + new paths. */ + +static u32 count_bytes(u8* mem) { + + u32* ptr = (u32*)mem; + u32 i = (MAP_SIZE >> 2); + u32 ret = 0; + + while (i--) { + + u32 v = *(ptr++); + + if (!v) continue; + if (v & FF(0)) ret++; + if (v & FF(1)) ret++; + if (v & FF(2)) ret++; + if (v & FF(3)) ret++; + + } + + return ret; + +} + + +/* Count the number of non-255 bytes set in the bitmap. Used strictly for the + status screen, several calls per second or so. */ + +static u32 count_non_255_bytes(u8* mem) { + + u32* ptr = (u32*)mem; + u32 i = (MAP_SIZE >> 2); + u32 ret = 0; + + while (i--) { + + u32 v = *(ptr++); + + /* This is called on the virgin bitmap, so optimize for the most likely + case. */ + + if (v == 0xffffffff) continue; + if ((v & FF(0)) != FF(0)) ret++; + if ((v & FF(1)) != FF(1)) ret++; + if ((v & FF(2)) != FF(2)) ret++; + if ((v & FF(3)) != FF(3)) ret++; + + } + + return ret; + +} + + +/* Destructively simplify trace by eliminating hit count information + and replacing it with 0x80 or 0x01 depending on whether the tuple + is hit or not. Called on every new crash or timeout, should be + reasonably fast. */ + +static u8 simplify_lookup[256] = {0}; + +#ifdef __x86_64__ + +static void simplify_trace(u64* mem) { + + u32 i = MAP_SIZE >> 3; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u8* mem8 = (u8*)mem; + + mem8[0] = simplify_lookup[mem8[0]]; + mem8[1] = simplify_lookup[mem8[1]]; + mem8[2] = simplify_lookup[mem8[2]]; + mem8[3] = simplify_lookup[mem8[3]]; + mem8[4] = simplify_lookup[mem8[4]]; + mem8[5] = simplify_lookup[mem8[5]]; + mem8[6] = simplify_lookup[mem8[6]]; + mem8[7] = simplify_lookup[mem8[7]]; + + } else *mem = 0x0101010101010101ULL; + + mem++; + + } + +} + +#else + +static void simplify_trace(u32* mem) { + + u32 i = MAP_SIZE >> 2; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u8* mem8 = (u8*)mem; + + mem8[0] = simplify_lookup[mem8[0]]; + mem8[1] = simplify_lookup[mem8[1]]; + mem8[2] = simplify_lookup[mem8[2]]; + mem8[3] = simplify_lookup[mem8[3]]; + + } else *mem = 0x01010101; + + mem++; + } + +} + +#endif /* ^__x86_64__ */ + + +/* Destructively classify execution counts in a trace. This is used as a + preprocessing step for any newly acquired traces. Called on every exec, + must be fast. */ + +static u8 count_class_lookup8[256] = {0}; + +static u16 count_class_lookup16[65536]; + +void memset_fucking_array(){ + simplify_lookup[0] = 1; + memset(simplify_lookup+1, 128, 255); + + count_class_lookup8[0] = 0; + count_class_lookup8[1] = 1; + count_class_lookup8[2] = 2; + count_class_lookup8[3] = 4; + memset(count_class_lookup8 + 4, 8, 7 - 4 + 1); + memset(count_class_lookup8 + 8, 16, 15 - 8 + 1); + memset(count_class_lookup8 + 16, 32, 32 - 16); + memset(count_class_lookup8 + 32, 64, 128 - 32); + memset(count_class_lookup8 + 128, 128, 128); +} + +EXP_ST void init_count_class16(void) { + + u32 b1, b2; + + for (b1 = 0; b1 < 256; b1++) + for (b2 = 0; b2 < 256; b2++) + count_class_lookup16[(b1 << 8) + b2] = + (count_class_lookup8[b1] << 8) | + count_class_lookup8[b2]; + +} + + +#ifdef __x86_64__ + +static inline void classify_counts(u64* mem) { + + u32 i = MAP_SIZE >> 3; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u16* mem16 = (u16*)mem; + + mem16[0] = count_class_lookup16[mem16[0]]; + mem16[1] = count_class_lookup16[mem16[1]]; + mem16[2] = count_class_lookup16[mem16[2]]; + mem16[3] = count_class_lookup16[mem16[3]]; + + } + + mem++; + + } + +} + +#else + +static inline void classify_counts(u32* mem) { + + u32 i = MAP_SIZE >> 2; + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { + + u16* mem16 = (u16*)mem; + + mem16[0] = count_class_lookup16[mem16[0]]; + mem16[1] = count_class_lookup16[mem16[1]]; + + } + + mem++; + + } + +} + +#endif /* ^__x86_64__ */ + + +/* Get rid of shared memory (atexit handler). */ + +static void remove_shm(void) { + + shmctl(shm_id, IPC_RMID, NULL); + +} + + +/* Compact trace bytes into a smaller bitmap. We effectively just drop the + count information here. This is called only sporadically, for some + new paths. */ + +static void minimize_bits(u8* dst, u8* src) { + + u32 i = 0; + + while (i < MAP_SIZE) { + + if (*(src++)) dst[i >> 3] |= 1 << (i & 7); + i++; + + } + +} + + +/* When we bump into a new path, we call this to see if the path appears + more "favorable" than any of the existing ones. The purpose of the + "favorables" is to have a minimal set of paths that trigger all the bits + seen in the bitmap so far, and focus on fuzzing them at the expense of + the rest. + + The first step of the process is to maintain a list of top_rated[] entries + for every byte in the bitmap. We win that slot if there is no previous + contender, or if the contender has a more favorable speed x size factor. */ + +static void update_bitmap_score(struct queue_entry* q) { + + u32 i; + u64 fav_factor = q->exec_us * q->len; + + /* For every byte set in trace_bits[], see if there is a previous winner, + and how it compares to us. */ + + for (i = 0; i < MAP_SIZE; i++) + + if (trace_bits[i]) { + + if (top_rated[i]) { + + /* Faster-executing or smaller test cases are favored. */ + + if (fav_factor > top_rated[i]->exec_us * top_rated[i]->len) continue; + + /* Looks like we're going to win. Decrease ref count for the + previous winner, discard its trace_bits[] if necessary. */ + + if (!--top_rated[i]->tc_ref) { + ck_free(top_rated[i]->trace_mini); + top_rated[i]->trace_mini = 0; + } + + } + + /* Insert ourselves as the new winner. */ + + top_rated[i] = q; + q->tc_ref++; + + if (!q->trace_mini) { + q->trace_mini = ck_alloc(MAP_SIZE >> 3); + minimize_bits(q->trace_mini, trace_bits); + } + + score_changed = 1; + + } + +} + + +/* The second part of the mechanism discussed above is a routine that + goes over top_rated[] entries, and then sequentially grabs winners for + previously-unseen bytes (temp_v) and marks them as favored, at least + until the next run. The favored entries are given more air time during + all fuzzing steps. */ + +static void cull_queue(void) { + + struct queue_entry* q; + static u8 temp_v[MAP_SIZE >> 3]; + u32 i; + + if (dumb_mode || !score_changed) return; + + score_changed = 0; + + memset(temp_v, 255, MAP_SIZE >> 3); + + queued_favored = 0; + pending_favored = 0; + + q = queue; + + while (q) { + q->favored = 0; + q = q->next; + } + + /* Let's see if anything in the bitmap isn't captured in temp_v. + If yes, and if it has a top_rated[] contender, let's use it. */ + + for (i = 0; i < MAP_SIZE; i++) + if (top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { + + u32 j = MAP_SIZE >> 3; + + /* Remove all bits belonging to the current entry from temp_v. */ + + while (j--) + if (top_rated[i]->trace_mini[j]) + temp_v[j] &= ~top_rated[i]->trace_mini[j]; + + top_rated[i]->favored = 1; + queued_favored++; + + if (!top_rated[i]->was_fuzzed) pending_favored++; + + } + + q = queue; + + while (q) { + mark_as_redundant(q, !q->favored); + q = q->next; + } + +} + + +/* Configure shared memory and virgin_bits. This is called at startup. */ + +EXP_ST void setup_shm(void) { + + u8* shm_str; + + if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); + + memset(virgin_tmout, 255, MAP_SIZE); + memset(virgin_crash, 255, MAP_SIZE); + + shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); + + if (shm_id < 0) PFATAL("shmget() failed"); + + atexit(remove_shm); + + shm_str = alloc_printf("%d", shm_id); + + /* If somebody is asking us to fuzz instrumented binaries in dumb mode, + we don't want them to detect instrumentation, since we won't be sending + fork server commands. This should be replaced with better auto-detection + later on, perhaps? */ + + if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); + ck_free(shm_str); + trace_bits = shmat(shm_id, NULL, 0); + + if (!trace_bits) PFATAL("shmat() failed"); + +} + + +/* Load postprocessor, if available. */ + +static void setup_post(void) { + + void* dh; + u8* fn = getenv("AFL_POST_LIBRARY"); + u32 tlen = 6; + + if (!fn) return; + + ACTF("Loading postprocessor from '%s'...", fn); + + dh = dlopen(fn, RTLD_NOW); + if (!dh) FATAL("%s", dlerror()); + + post_handler = dlsym(dh, "afl_postprocess"); + if (!post_handler) FATAL("Symbol 'afl_postprocess' not found."); + + /* Do a quick test. It's better to segfault now than later =) */ + + post_handler("hello", &tlen); + + OKF("Postprocessor installed successfully."); + +} + + +/* Read all testcases from the input directory, then queue them for testing. + Called at startup. */ + +static void read_testcases(void) { + + struct dirent **nl; + s32 nl_cnt; + u32 i; + u8* fn; + + /* Auto-detect non-in-place resumption attempts. */ + + fn = alloc_printf("%s/queue", in_dir); + if (!access(fn, F_OK)) in_dir = fn; else ck_free(fn); + + ACTF("Scanning '%s'...", in_dir); + + /* We use scandir() + alphasort() rather than readdir() because otherwise, + the ordering of test cases would vary somewhat randomly and would be + difficult to control. */ + + nl_cnt = scandir(in_dir, &nl, NULL, alphasort); + + if (nl_cnt < 0) { + + if (errno == ENOENT || errno == ENOTDIR) + + SAYF("\n" cLRD "[-] " cRST + "The input directory does not seem to be valid - try again. The fuzzer needs\n" + " one or more test case to start with - ideally, a small file under 1 kB\n" + " or so. The cases must be stored as regular files directly in the input\n" + " directory.\n"); + + PFATAL("Unable to open '%s'", in_dir); + + } + + if (shuffle_queue && nl_cnt > 1) { + + ACTF("Shuffling queue..."); + shuffle_ptrs((void**)nl, nl_cnt); + + } + + for (i = 0; i < nl_cnt; i++) { + + struct stat st; + + u8* fn = alloc_printf("%s/%s", in_dir, nl[i]->d_name); + u8* dfn = alloc_printf("%s/.state/deterministic_done/%s", in_dir, nl[i]->d_name); + + u8 passed_det = 0; + + free(nl[i]); /* not tracked */ + + if (lstat(fn, &st) || access(fn, R_OK)) + PFATAL("Unable to access '%s'", fn); + + /* This also takes care of . and .. */ + + if (!S_ISREG(st.st_mode) || !st.st_size || strstr((char *)fn, "/README.txt")) { + + ck_free(fn); + ck_free(dfn); + continue; + + } + + if (st.st_size > MAX_FILE) + FATAL("Test case '%s' is too big (%s, limit is %s)", fn, + DMS(st.st_size), DMS(MAX_FILE)); + + /* Check for metadata that indicates that deterministic fuzzing + is complete for this entry. We don't want to repeat deterministic + fuzzing when resuming aborted scans, because it would be pointless + and probably very time-consuming. */ + + if (!access(dfn, F_OK)) passed_det = 1; + ck_free(dfn); + + add_to_queue(fn, st.st_size, passed_det); + + } + + free(nl); /* not tracked */ + + if (!queued_paths) { + + SAYF("\n" cLRD "[-] " cRST + "Looks like there are no valid test cases in the input directory! The fuzzer\n" + " needs one or more test case to start with - ideally, a small file under\n" + " 1 kB or so. The cases must be stored as regular files directly in the\n" + " input directory.\n"); + + FATAL("No usable test cases in '%s'", in_dir); + + } + + last_path_time = 0; + queued_at_start = queued_paths; + +} + + +/* Helper function for load_extras. */ + +static int compare_extras_len(const void* p1, const void* p2) { + struct extra_data *e1 = (struct extra_data*)p1, + *e2 = (struct extra_data*)p2; + + return e1->len - e2->len; +} + +static int compare_extras_use_d(const void* p1, const void* p2) { + struct extra_data *e1 = (struct extra_data*)p1, + *e2 = (struct extra_data*)p2; + + return e2->hit_cnt - e1->hit_cnt; +} + + +/* Read extras from a file, sort by size. */ + +static void load_extras_file(u8* fname, u32* min_len, u32* max_len, + u32 dict_level) { + + FILE* f; + u8 buf[MAX_LINE]; + u8 *lptr; + u32 cur_line = 0; + + f = fopen(fname, "r"); + + if (!f) PFATAL("Unable to open '%s'", fname); + + while ((lptr = fgets(buf, MAX_LINE, f))) { + + u8 *rptr, *wptr; + u32 klen = 0; + + cur_line++; + + /* Trim on left and right. */ + + while (isspace(*lptr)) lptr++; + + rptr = lptr + strlen(lptr) - 1; + while (rptr >= lptr && isspace(*rptr)) rptr--; + rptr++; + *rptr = 0; + + /* Skip empty lines and comments. */ + + if (!*lptr || *lptr == '#') continue; + + /* All other lines must end with '"', which we can consume. */ + + rptr--; + + if (rptr < lptr || *rptr != '"') + FATAL("Malformed name=\"value\" pair in line %u.", cur_line); + + *rptr = 0; + + /* Skip alphanumerics and dashes (label). */ + + while (isalnum(*lptr) || *lptr == '_') lptr++; + + /* If @number follows, parse that. */ + + if (*lptr == '@') { + + lptr++; + if (atoi(lptr) > dict_level) continue; + while (isdigit(*lptr)) lptr++; + + } + + /* Skip whitespace and = signs. */ + + while (isspace(*lptr) || *lptr == '=') lptr++; + + /* Consume opening '"'. */ + + if (*lptr != '"') + FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); + + lptr++; + + if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); + + /* Okay, let's allocate memory and copy data between "...", handling + \xNN escaping, \\, and \". */ + + extras = ck_realloc_block(extras, (extras_cnt + 1) * + sizeof(struct extra_data)); + + wptr = extras[extras_cnt].data = ck_alloc(rptr - lptr); + + while (*lptr) { + + char* hexdigits = "0123456789abcdef"; + + switch (*lptr) { + + case 1 ... 31: + case 128 ... 255: + FATAL("Non-printable characters in line %u.", cur_line); + + case '\\': + + lptr++; + + if (*lptr == '\\' || *lptr == '"') { + *(wptr++) = *(lptr++); + klen++; + break; + } + + if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) + FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); + + *(wptr++) = + ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) | + (strchr(hexdigits, tolower(lptr[2])) - hexdigits); + + lptr += 3; + klen++; + + break; + + default: + + *(wptr++) = *(lptr++); + klen++; + + } + + } + + extras[extras_cnt].len = klen; + + if (extras[extras_cnt].len > MAX_DICT_FILE) + FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, + DMS(klen), DMS(MAX_DICT_FILE)); + + if (*min_len > klen) *min_len = klen; + if (*max_len < klen) *max_len = klen; + + extras_cnt++; + + } + + fclose(f); + +} + + +/* Read extras from the extras directory and sort them by size. */ + +static void load_extras(u8* dir) { + + DIR* d; + struct dirent* de; + u32 min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0; + u8* x; + + /* If the name ends with @, extract level and continue. */ + + if ((x = strchr((char *)dir, '@'))) { + + *x = 0; + dict_level = atoi(x + 1); + + } + + ACTF("Loading extra dictionary from '%s' (level %u)...", dir, dict_level); + + d = opendir(dir); + + if (!d) { + + if (errno == ENOTDIR) { + load_extras_file(dir, &min_len, &max_len, dict_level); + goto check_and_sort; + } + + PFATAL("Unable to open '%s'", dir); + + } + + if (x) FATAL("Dictionary levels not supported for directories."); + + while ((de = readdir(d))) { + + struct stat st; + u8* fn = alloc_printf("%s/%s", dir, de->d_name); + s32 fd; + + if (lstat(fn, &st) || access(fn, R_OK)) + PFATAL("Unable to access '%s'", fn); + + /* This also takes care of . and .. */ + if (!S_ISREG(st.st_mode) || !st.st_size) { + + ck_free(fn); + continue; + + } + + if (st.st_size > MAX_DICT_FILE) + FATAL("Extra '%s' is too big (%s, limit is %s)", fn, + DMS(st.st_size), DMS(MAX_DICT_FILE)); + + if (min_len > st.st_size) min_len = st.st_size; + if (max_len < st.st_size) max_len = st.st_size; + + extras = ck_realloc_block(extras, (extras_cnt + 1) * + sizeof(struct extra_data)); + + extras[extras_cnt].data = ck_alloc(st.st_size); + extras[extras_cnt].len = st.st_size; + + fd = open(fn, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", fn); + + ck_read(fd, extras[extras_cnt].data, st.st_size, fn); + + close(fd); + ck_free(fn); + + extras_cnt++; + + } + + closedir(d); + +check_and_sort: + + if (!extras_cnt) FATAL("No usable files in '%s'", dir); + + qsort(extras, extras_cnt, sizeof(struct extra_data), compare_extras_len); + + OKF("Loaded %u extra tokens, size range %s to %s.", extras_cnt, + DMS(min_len), DMS(max_len)); + + if (max_len > 32) + WARNF("Some tokens are relatively large (%s) - consider trimming.", + DMS(max_len)); + + if (extras_cnt > MAX_DET_EXTRAS) + WARNF("More than %u tokens - will use them probabilistically.", + MAX_DET_EXTRAS); + +} + + + + +/* Helper function for maybe_add_auto() */ + +static inline u8 memcmp_nocase(u8* m1, u8* m2, u32 len) { + + while (len--) if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1; + return 0; + +} + + +/* Maybe add automatic extra. */ + +static void maybe_add_auto(u8* mem, u32 len) { + + u32 i; + + /* Allow users to specify that they don't want auto dictionaries. */ + + if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return; + + /* Skip runs of identical bytes. */ + + for (i = 1; i < len; i++) + if (mem[0] ^ mem[i]) break; + + if (i == len) return; + + /* Reject builtin interesting values. */ + + if (len == 2) { + + i = sizeof(interesting_16) >> 1; + + while (i--) + if (*((u16*)mem) == interesting_16[i] || + *((u16*)mem) == SWAP16(interesting_16[i])) return; + + } + + if (len == 4) { + + i = sizeof(interesting_32) >> 2; + + while (i--) + if (*((u32*)mem) == interesting_32[i] || + *((u32*)mem) == SWAP32(interesting_32[i])) return; + + } + + /* Reject anything that matches existing extras. Do a case-insensitive + match. We optimize by exploiting the fact that extras[] are sorted + by size. */ + + for (i = 0; i < extras_cnt; i++) + if (extras[i].len >= len) break; + + for (; i < extras_cnt && extras[i].len == len; i++) + if (!memcmp_nocase(extras[i].data, mem, len)) return; + + /* Last but not least, check a_extras[] for matches. There are no + guarantees of a particular sort order. */ + + auto_changed = 1; + + for (i = 0; i < a_extras_cnt; i++) { + + if (a_extras[i].len == len && !memcmp_nocase(a_extras[i].data, mem, len)) { + + a_extras[i].hit_cnt++; + goto sort_a_extras; + + } + + } + + /* At this point, looks like we're dealing with a new entry. So, let's + append it if we have room. Otherwise, let's randomly evict some other + entry from the bottom half of the list. */ + + if (a_extras_cnt < MAX_AUTO_EXTRAS) { + + a_extras = ck_realloc_block(a_extras, (a_extras_cnt + 1) * + sizeof(struct extra_data)); + + a_extras[a_extras_cnt].data = ck_memdup(mem, len); + a_extras[a_extras_cnt].len = len; + a_extras_cnt++; + + } else { + + i = MAX_AUTO_EXTRAS / 2 + + UR((MAX_AUTO_EXTRAS + 1) / 2); + + ck_free(a_extras[i].data); + + a_extras[i].data = ck_memdup(mem, len); + a_extras[i].len = len; + a_extras[i].hit_cnt = 0; + + } + +sort_a_extras: + + /* First, sort all auto extras by use count, descending order. */ + + qsort(a_extras, a_extras_cnt, sizeof(struct extra_data), + compare_extras_use_d); + + /* Then, sort the top USE_AUTO_EXTRAS entries by size. */ + + qsort(a_extras, MIN(USE_AUTO_EXTRAS, a_extras_cnt), + sizeof(struct extra_data), compare_extras_len); + +} + + +/* Save automatically generated extras. */ + +static void save_auto(void) { + + u32 i; + + if (!auto_changed) return; + auto_changed = 0; + + for (i = 0; i < MIN(USE_AUTO_EXTRAS, a_extras_cnt); i++) { + + u8* fn = alloc_printf("%s/queue/.state/auto_extras/auto_%06u", out_dir, i); + s32 fd; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_write(fd, a_extras[i].data, a_extras[i].len, fn); + + close(fd); + ck_free(fn); + + } + +} + + +/* Load automatically generated extras. */ + +static void load_auto(void) { + + u32 i; + + for (i = 0; i < USE_AUTO_EXTRAS; i++) { + + u8 tmp[MAX_AUTO_EXTRA + 1]; + u8* fn = alloc_printf("%s/.state/auto_extras/auto_%06u", in_dir, i); + s32 fd, len; + + fd = open(fn, O_RDONLY, 0600); + + if (fd < 0) { + + if (errno != ENOENT) PFATAL("Unable to open '%s'", fn); + ck_free(fn); + break; + + } + + /* We read one byte more to cheaply detect tokens that are too + long (and skip them). */ + + len = read(fd, tmp, MAX_AUTO_EXTRA + 1); + + if (len < 0) PFATAL("Unable to read from '%s'", fn); + + if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) + maybe_add_auto(tmp, len); + + close(fd); + ck_free(fn); + + } + + if (i) OKF("Loaded %u auto-discovered dictionary tokens.", i); + else OKF("No auto-generated dictionary tokens to reuse."); + +} + + +/* Destroy extras. */ + +static void destroy_extras(void) { + + u32 i; + + for (i = 0; i < extras_cnt; i++) + ck_free(extras[i].data); + + ck_free(extras); + + for (i = 0; i < a_extras_cnt; i++) + ck_free(a_extras[i].data); + + ck_free(a_extras); + +} + + +/* Spin up fork server (instrumented mode only). The idea is explained here: + + http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html + + In essence, the instrumentation allows us to skip execve(), and just keep + cloning a stopped child. So, we just execute once, and then send commands + through a pipe. The other part of this logic is in afl-as.h. */ + +EXP_ST void init_forkserver(char** argv) { + + static struct itimerval it; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; + ACTF("Spinning up the fork server..."); + + if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); + + forksrv_pid = fork(); + + if (forksrv_pid < 0) PFATAL("fork() failed"); + + if (!forksrv_pid) { + + struct rlimit r; + + /* Umpf. On OpenBSD, the default fd limit for root users is set to + soft 128. Let's try to fix that... */ + + if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) { + + r.rlim_cur = FORKSRV_FD + 2; + setrlimit(RLIMIT_NOFILE, &r); /* Ignore errors */ + + } + + if (mem_limit) { + + r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 50; + +#ifdef RLIMIT_AS + + setrlimit(RLIMIT_AS, &r); /* Ignore errors */ + +#else + + /* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but + according to reliable sources, RLIMIT_DATA covers anonymous + maps - so we should be getting good protection against OOM bugs. */ + + setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ + +#endif /* ^RLIMIT_AS */ + + + } + + /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered + before the dump is complete. */ + + r.rlim_max = r.rlim_cur = 0; + + setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + + /* Isolate the process and configure standard descriptors. If out_file is + specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ + + setsid(); + + dup2(dev_null_fd, 1); + dup2(dev_null_fd, 2); + + if (out_file) { + + dup2(dev_null_fd, 0); + + } else { + + dup2(out_fd, 0); + close(out_fd); + + } + + /* Set up control and status pipes, close the unneeded original fds. */ + + if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); + if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed"); + + close(ctl_pipe[0]); + close(ctl_pipe[1]); + close(st_pipe[0]); + close(st_pipe[1]); + + close(out_dir_fd); + close(dev_null_fd); + close(dev_urandom_fd); + close(fileno(plot_file)); + + /* This should improve performance a bit, since it stops the linker from + doing extra work post-fork(). */ + + if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); + + /* Set sane defaults for ASAN if nothing else specified. */ + + setenv("ASAN_OPTIONS", "abort_on_error=1:" + "detect_leaks=0:" + "symbolize=0:" + "allocator_may_return_null=1", 0); + + /* MSAN is tricky, because it doesn't support abort_on_error=1 at this + point. So, we do this in a very hacky way. */ + + setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" + "symbolize=0:" + "abort_on_error=1:" + "allocator_may_return_null=1:" + "msan_track_origins=0", 0); + + /* char * tmp_target_path = "/usr/local/mysql/bin/mysqld"; + char * tmp_argv[] = {"/usr/local/mysql/bin/mysqld", + "--basedir=/usr/local/mysql", + "--datadir=/usr/local/mysql/data", + "--plugin-dir=/usr/local/mysql/lib/plugin", + "--user=mysql", + "--log-error=lrs-dwu01.err", + "--pid-file=lrs-dwu01.pid", + "--socket=/tmp/mysql.sock", + NULL}; + execv(tmp_target_path, tmp_argv); //改参数把,别改这里了,我再去看看那个启动参数 +*/ + /* Use a distinctive bitmap signature to tell the parent about execv() + falling through. */ + + *(u32*)trace_bits = EXEC_FAIL_SIG; + exit(0); + + } + + /* Close the unneeded endpoints. */ + + close(ctl_pipe[0]); + close(st_pipe[1]); + + fsrv_ctl_fd = ctl_pipe[1]; + fsrv_st_fd = st_pipe[0]; + + + /* Wait for the fork server to come up, but don't wait too long. */ + + it.it_value.tv_sec = ((exec_tmout * FORK_WAIT_MULT) / 1000); + it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + + setitimer(ITIMER_REAL, &it, NULL); + + rlen = read(fsrv_st_fd, &status, 4); + child_pid = status; + assert(child_pid != -1); + + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &it, NULL); + + /* If we have a four-byte "hello" message from the server, we're all set. + Otherwise, try to figure out what went wrong. */ + + if (rlen == 4) { + OKF("All right - fork server is up."); + return; + } + + if (child_timed_out) + FATAL("Timeout while initializing fork server (adjusting -t may help)"); + + if (waitpid(forksrv_pid, &status, 0) <= 0) + PFATAL("waitpid() failed"); + + if (WIFSIGNALED(status)) { + + if (mem_limit && mem_limit < 500 && uses_asan) { + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the target binary crashed suddenly, before receiving any input\n" + " from the fuzzer! Since it seems to be built with ASAN and you have a\n" + " restrictive memory limit configured, this is expected; please read\n" + " %s/notes_for_asan.txt for help.\n", doc_path); + + } else if (!mem_limit) { + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the target binary crashed suddenly, before receiving any input\n" + " from the fuzzer! There are several probable explanations:\n\n" + + " - The binary is just buggy and explodes entirely on its own. If so, you\n" + " need to fix the underlying problem or find a better replacement.\n\n" + +#ifdef __APPLE__ + + " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" + " break afl-fuzz performance optimizations when running platform-specific\n" + " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" + +#endif /* __APPLE__ */ + + " - Less likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n"); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the target binary crashed suddenly, before receiving any input\n" + " from the fuzzer! There are several probable explanations:\n\n" + + " - The current memory limit (%s) is too restrictive, causing the\n" + " target to hit an OOM condition in the dynamic linker. Try bumping up\n" + " the limit with the -m setting in the command line. A simple way confirm\n" + " this diagnosis would be:\n\n" + +#ifdef RLIMIT_AS + " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#else + " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#endif /* ^RLIMIT_AS */ + + " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" + " estimate the required amount of virtual memory for the binary.\n\n" + + " - The binary is just buggy and explodes entirely on its own. If so, you\n" + " need to fix the underlying problem or find a better replacement.\n\n" + +#ifdef __APPLE__ + + " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" + " break afl-fuzz performance optimizations when running platform-specific\n" + " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" + +#endif /* __APPLE__ */ + + " - Less likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n", + DMS(mem_limit << 20), mem_limit - 1); + + } + + FATAL("Fork server crashed with signal %d", WTERMSIG(status)); + + } + + if (*(u32*)trace_bits == EXEC_FAIL_SIG) + FATAL("Unable to execute target application ('%s')", argv[0]); + + if (mem_limit && mem_limit < 500 && uses_asan) { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, looks like the target binary terminated before we could complete a\n" + " handshake with the injected code. Since it seems to be built with ASAN and\n" + " you have a restrictive memory limit configured, this is expected; please\n" + " read %s/notes_for_asan.txt for help.\n", doc_path); + + } else if (!mem_limit) { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, looks like the target binary terminated before we could complete a\n" + " handshake with the injected code. Perhaps there is a horrible bug in the\n" + " fuzzer. Poke for troubleshooting tips.\n"); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, looks like the target binary terminated before we could complete a\n" + " handshake with the injected code. There are %s probable explanations:\n\n" + + "%s" + " - The current memory limit (%s) is too restrictive, causing an OOM\n" + " fault in the dynamic linker. This can be fixed with the -m option. A\n" + " simple way to confirm the diagnosis may be:\n\n" + +#ifdef RLIMIT_AS + " ( ulimit -Sv $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#else + " ( ulimit -Sd $[%llu << 10]; /path/to/fuzzed_app )\n\n" +#endif /* ^RLIMIT_AS */ + + " Tip: you can use http://jwilk.net/software/recidivm to quickly\n" + " estimate the required amount of virtual memory for the binary.\n\n" + + " - Less likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n", + getenv(DEFER_ENV_VAR) ? "three" : "two", + getenv(DEFER_ENV_VAR) ? + " - You are using deferred forkserver, but __AFL_INIT() is never\n" + " reached before the program terminates.\n\n" : "", + DMS(mem_limit << 20), mem_limit - 1); + + } + + FATAL("Fork server handshake failed"); + +} + +/* Execute target application, monitoring for timeouts. Return status + information. The called program will update trace_bits[]. */ + +int counter; +static u8 run_target(char** argv, u32 timeout) { + + static struct itimerval it; + static u32 prev_timed_out = 0; + static u64 exec_ms = 0; + int status = 0; + u32 tb4; + + child_timed_out = 0; + + /* After this memset, trace_bits[] are effectively volatile, so we + must prevent any earlier operations from venturing into that + territory. */ + + memset(trace_bits, 0, MAP_SIZE); + MEM_BARRIER(); + +//********************************** + + vaild_flag = 0; + + SQLSTATUS result = g_connector.execute(g_current_sql); + + if (result == SQLSTATUS::ssConnectFailed) { + while (1) { + sleep(0.1); + + g_connector.start_db(file, options); + result = g_connector.execute(g_current_sql); + + if ((result != SQLSTATUS::ssConnectFailed) || stop_soon) { + break; + } + } + } + + if(result == SQLSTATUS::ssServerCrash){ + status = FAULT_CRASH; + }else{ + if(result == SQLSTATUS::ssNormal){ + vaild_flag = 1; + total_vaild++; + } + + status = FAULT_NONE; + } + + total_execs++; + cur_execs++; + +//********************************** + + MEM_BARRIER(); + + tb4 = *(u32*)trace_bits; + +#ifdef __x86_64__ + classify_counts((u64*)trace_bits); +#else + classify_counts((u32*)trace_bits); +#endif /* ^__x86_64__ */ + + return status; +} + + +/* Write modified data to file for testing. If out_file is set, the old file + is unlinked and a new one is created. Otherwise, out_fd is rewound and + truncated. */ + +static void write_to_testcase(void* mem, u32 len) { + + g_current_sql = (char *)mem; + return ; + +} + + +/* The same, but with an adjustable gap. Used for trimming. */ + +static void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) { + + s32 fd = out_fd; + u32 tail_len = len - skip_at - skip_len; + + if (out_file) { + + unlink(out_file); /* Ignore errors. */ + + fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", out_file); + + } else lseek(fd, 0, SEEK_SET); + + if (skip_at) ck_write(fd, mem, skip_at, out_file); + + if (tail_len) ck_write(fd, mem + skip_at + skip_len, tail_len, out_file); + + if (!out_file) { + + if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed"); + lseek(fd, 0, SEEK_SET); + + } else close(fd); + +} + + +static void show_stats(void); + +/* Calibrate a new test case. This is done when processing the input directory + to warn about flaky or otherwise problematic test cases early on; and when + new paths are discovered to detect variable behavior and so on. */ + +static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem, + u32 handicap, u8 from_queue) { + + static u8 first_trace[MAP_SIZE]; + + u8 fault = 0, new_bits = 0, var_detected = 0, + first_run = (q->exec_cksum == 0); + + u64 start_us, stop_us; + + s32 old_sc = stage_cur, old_sm = stage_max; + u32 use_tmout = exec_tmout; + u8* old_sn = stage_name; + + /* Be a bit more generous about timeouts when resuming sessions, or when + trying to calibrate already-added finds. This helps avoid trouble due + to intermittent latency. */ + + if (!from_queue || resuming_fuzz) + use_tmout = MAX(exec_tmout + CAL_TMOUT_ADD, + exec_tmout * CAL_TMOUT_PERC / 100); + + q->cal_failed++; + + stage_name = "calibration"; + stage_max = fast_cal ? 3 : CAL_CYCLES; + + /* Make sure the forkserver is up before we do anything, and let's not + count its spin-up time toward binary calibration. */ + + if (dumb_mode != 1 && !no_forkserver && !forksrv_pid){ + /* + int idx = 0; + cout << "Init fork server arguments: " << endl; + while(auto s = argv[idx]){ + cout << argv[idx++] << endl; + } + cin >> idx; + */ + //init_forkserver(argv); + } + + + if (q->exec_cksum) memcpy(first_trace, trace_bits, MAP_SIZE); + + start_us = get_cur_time_us(); + + for (stage_cur = 0; stage_cur < 1; stage_cur++) { + + u32 cksum; + + if (!first_run && !(stage_cur % stats_update_freq)) show_stats(); + + write_to_testcase(use_mem, q->len); + + fault = run_target(argv, use_tmout); + + /* stop_soon is set by the handler for Ctrl+C. When it's pressed, + we want to bail out quickly. */ + + if (stop_soon || fault != crash_mode) goto abort_calibration; + + if (!dumb_mode && !stage_cur && !count_bytes(trace_bits)) { + fault = FAULT_NOINST; + goto abort_calibration; + } + + cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + + if (q->exec_cksum != cksum) { + + u8 hnb = has_new_bits(virgin_bits); + if (hnb > new_bits) new_bits = hnb; + + if (q->exec_cksum) { + + u32 i; + + for (i = 0; i < MAP_SIZE; i++) { + + if (!var_bytes[i] && first_trace[i] != trace_bits[i]) { + + var_bytes[i] = 1; + virgin_bits[i] = 0; + stage_max = CAL_CYCLES_LONG; + + } + + } + + var_detected = 1; + + } else { + + q->exec_cksum = cksum; + memcpy(first_trace, trace_bits, MAP_SIZE); + + } + + } + + } + + stop_us = get_cur_time_us(); + + total_cal_us += stop_us - start_us; + total_cal_cycles += stage_max; + + /* OK, let's collect some stats about the performance of this test case. + This is used for fuzzing air time calculations in calculate_score(). */ + + q->exec_us = (stop_us - start_us) / stage_max; + q->bitmap_size = count_bytes(trace_bits); + q->handicap = handicap; + q->cal_failed = 0; + + total_bitmap_size += q->bitmap_size; + total_bitmap_entries++; + + update_bitmap_score(q); + + /* If this case didn't result in new output from the instrumentation, tell + parent. This is a non-critical problem, but something to warn the user + about. */ + + if (!dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS; + +abort_calibration: + + if (new_bits == 2 && !q->has_new_cov) { + q->has_new_cov = 1; + queued_with_cov++; + } + + /* Mark variable paths. */ + + if (var_detected) { + + var_byte_count = count_bytes(var_bytes); + + if (!q->var_behavior) { + mark_as_variable(q); + queued_variable++; + } + + } + + stage_name = old_sn; + stage_cur = old_sc; + stage_max = old_sm; + + if (!first_run) show_stats(); + + return fault; + +} + + +/* Examine map coverage. Called once, for first test case. */ + +static void check_map_coverage(void) { + + u32 i; + + if (count_bytes(trace_bits) < 100) return; + + for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; i++) + if (trace_bits[i]) return; + + WARNF("Recompile binary with newer version of afl to improve coverage!"); + +} + + +/* Perform dry run of all test cases to confirm that the app is working as + expected. This is done only for the initial inputs, and only once. */ + +static void perform_dry_run(char** argv) { + + struct queue_entry* q = queue; + u32 cal_failures = 0; + u8* skip_crashes = getenv("AFL_SKIP_CRASHES"); + + while (q) { + + u8* use_mem; + u8 res; + s32 fd; + + u8* fn = strrchr((char *)q->fname, '/') + 1; + + ACTF("Attempting dry run with '%s'...", fn); + + fd = open(q->fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", q->fname); + + use_mem = (u8*)malloc(q->len + 1); + + if (read(fd, use_mem, q->len) != q->len) + FATAL("Short read from '%s'", q->fname); + + close(fd); + +//********************************* + + use_mem[q->len] = '\0'; + + IR* root = g_mutator.IR_parser(use_mem); + free(use_mem); + + if (root == nullptr) { + q = q->next; + continue; + } + + string ir_str = root->to_string(); + + char* tmp_str = ir_str.c_str(); + int siz = ir_str.size(); + + q->len = siz; + + res = calibrate_case(argv, q, tmp_str, 0, 1); + + if (stop_soon) return; + + //********************************* + + if (res == crash_mode || res == FAULT_NOBITS) + SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, + q->len, q->bitmap_size, q->exec_us); + + switch (res) { + + case FAULT_NONE: + + if (q == queue) check_map_coverage(); + + if (crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); + + break; + + case FAULT_TMOUT: + + if (timeout_given) { + + /* The -t nn+ syntax in the command line sets timeout_given to '2' and + instructs afl-fuzz to tolerate but skip queue entries that time + out. */ + + if (timeout_given > 1) { + WARNF("Test case results in a timeout (skipping)"); + q->cal_failed = CAL_CHANCES; + cal_failures++; + break; + } + + SAYF("\n" cLRD "[-] " cRST + "The program took more than %u ms to process one of the initial test cases.\n" + " Usually, the right thing to do is to relax the -t option - or to delete it\n" + " altogether and allow the fuzzer to auto-calibrate. That said, if you know\n" + " what you are doing and want to simply skip the unruly test cases, append\n" + " '+' at the end of the value passed to -t ('-t %u+').\n", exec_tmout, + exec_tmout); + + FATAL("Test case '%s' results in a timeout", fn); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "The program took more than %u ms to process one of the initial test cases.\n" + " This is bad news; raising the limit with the -t option is possible, but\n" + " will probably make the fuzzing process extremely slow.\n\n" + + " If this test case is just a fluke, the other option is to just avoid it\n" + " altogether, and find one that is less of a CPU hog.\n", exec_tmout); + + FATAL("Test case '%s' results in a timeout", fn); + + } + + case FAULT_CRASH: + + if (crash_mode) break; + + if (skip_crashes) { + WARNF("Test case results in a crash (skipping)"); + q->cal_failed = CAL_CHANCES; + cal_failures++; + break; + } + + if (mem_limit) { + + SAYF("\n" cLRD "[-] " cRST + "Oops, the program crashed with one of the test cases provided. There are\n" + " several possible explanations:\n\n" + + " - The test case causes known crashes under normal working conditions. If\n" + " so, please remove it. The fuzzer should be seeded with interesting\n" + " inputs - but not ones that cause an outright crash.\n\n" + + " - The current memory limit (%s) is too low for this program, causing\n" + " it to die due to OOM when parsing valid files. To fix this, try\n" + " bumping it up with the -m setting in the command line. If in doubt,\n" + " try something along the lines of:\n\n" + +#ifdef RLIMIT_AS + " ( ulimit -Sv $[%llu << 10]; /path/to/binary [...] for troubleshooting tips.\n", + DMS(mem_limit << 20), mem_limit - 1, doc_path); + + } else { + + SAYF("\n" cLRD "[-] " cRST + "Oops, the program crashed with one of the test cases provided. There are\n" + " several possible explanations:\n\n" + + " - The test case causes known crashes under normal working conditions. If\n" + " so, please remove it. The fuzzer should be seeded with interesting\n" + " inputs - but not ones that cause an outright crash.\n\n" + +#ifdef __APPLE__ + + " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" + " break afl-fuzz performance optimizations when running platform-specific\n" + " binaries. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n" + +#endif /* __APPLE__ */ + + " - Least likely, there is a horrible bug in the fuzzer. If other options\n" + " fail, poke for troubleshooting tips.\n"); + + } + + FATAL("Test case '%s' results in a crash", fn); + + case FAULT_ERROR: + + FATAL("Unable to execute target application ('%s')", argv[0]); + + case FAULT_NOINST: + + FATAL("No instrumentation detected"); + + case FAULT_NOBITS: + + useless_at_start++; + + if (!in_bitmap && !shuffle_queue) + WARNF("No new instrumentation output, test case may be useless."); + + break; + + } + + if (q->var_behavior) WARNF("Instrumentation output varies across runs."); + + deep_delete(root); + + q = q->next; + + } + + if (cal_failures) { + + if (cal_failures == queued_paths) + FATAL("All test cases time out%s, giving up!", + skip_crashes ? " or crash" : ""); + + WARNF("Skipped %u test cases (%0.02f%%) due to timeouts%s.", cal_failures, + ((double)cal_failures) * 100 / queued_paths, + skip_crashes ? " or crashes" : ""); + + if (cal_failures * 5 > queued_paths) + WARNF(cLRD "High percentage of rejected test cases, check settings!"); + + } + + OKF("All test cases processed."); + +} + + +/* Helper function: link() if possible, copy otherwise. */ + +static void link_or_copy(u8* old_path, u8* new_path) { + + s32 i = link(old_path, new_path); + s32 sfd, dfd; + u8* tmp; + + if (!i) return; + + sfd = open(old_path, O_RDONLY); + if (sfd < 0) PFATAL("Unable to open '%s'", old_path); + + dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (dfd < 0) PFATAL("Unable to create '%s'", new_path); + + tmp = ck_alloc(64 * 1024); + + while ((i = read(sfd, tmp, 64 * 1024)) > 0) + ck_write(dfd, tmp, i, new_path); + + if (i < 0) PFATAL("read() failed"); + + ck_free(tmp); + close(sfd); + close(dfd); + +} + + +static void nuke_resume_dir(void); + +/* Create hard links for input test cases in the output directory, choosing + good names and pivoting accordingly. */ + +static void pivot_inputs(void) { + + struct queue_entry* q = queue; + u32 id = 0; + + ACTF("Creating hard links for all input files..."); + + while (q) { + + u8 *nfn, *rsl = strrchr((const char*)q->fname, '/'); + u32 orig_id; + + if (!rsl) rsl = q->fname; else rsl++; + + /* If the original file name conforms to the syntax and the recorded + ID matches the one we'd assign, just use the original file name. + This is valuable for resuming fuzzing runs. */ + +#ifndef SIMPLE_FILES +# define CASE_PREFIX "id:" +#else +# define CASE_PREFIX "id_" +#endif /* ^!SIMPLE_FILES */ + + if (!strncmp(rsl, CASE_PREFIX, 3) && + sscanf(rsl + 3, "%06u", &orig_id) == 1 && orig_id == id) { + + u8* src_str; + u32 src_id; + + resuming_fuzz = 1; + nfn = alloc_printf("%s/queue/%s", out_dir, rsl); + + /* Since we're at it, let's also try to find parent and figure out the + appropriate depth for this entry. */ + + src_str = strchr((char *)(rsl + 3), ':'); + + if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { + + struct queue_entry* s = queue; + while (src_id-- && s) s = s->next; + if (s) q->depth = s->depth + 1; + + if (max_depth < q->depth) max_depth = q->depth; + + } + + } else { + + /* No dice - invent a new name, capturing the original one as a + substring. */ + +#ifndef SIMPLE_FILES + + u8* use_name = strstr((const char*)rsl, ",orig:"); + + if (use_name) use_name += 6; else use_name = rsl; + nfn = alloc_printf("%s/queue/id:%06u,orig:%s", out_dir, id, use_name); + +#else + + nfn = alloc_printf("%s/queue/id_%06u", out_dir, id); + +#endif /* ^!SIMPLE_FILES */ + + } + + /* Pivot to the new queue entry. */ + + link_or_copy(q->fname, nfn); + ck_free(q->fname); + q->fname = nfn; + + /* Make sure that the passed_det value carries over, too. */ + + if (q->passed_det) mark_as_det_done(q); + + q = q->next; + id++; + + } + + if (in_place_resume) nuke_resume_dir(); + +} + + +#ifndef SIMPLE_FILES + +/* Construct a file name for a new test case, capturing the operation + that led to its discovery. Uses a static buffer. */ + +static u8* describe_op(u8 hnb) { + + static u8 ret[256]; + + if (syncing_party) { + + sprintf(ret, "sync:%s,src:%06u", syncing_party, syncing_case); + + } else { + + sprintf(ret, "src:%06u", current_entry); + + if (splicing_with >= 0) + sprintf(ret + strlen(ret), "+%06u", splicing_with); + + sprintf(ret + strlen(ret), ",op:%s", stage_short); + + if (stage_cur_byte >= 0) { + + sprintf(ret + strlen(ret), ",pos:%u", stage_cur_byte); + + if (stage_val_type != STAGE_VAL_NONE) + sprintf(ret + strlen(ret), ",val:%s%+d", + (stage_val_type == STAGE_VAL_BE) ? "be:" : "", + stage_cur_val); + + } else sprintf(ret + strlen(ret), ",rep:%u", stage_cur_val); + + } + + if (hnb == 2) strcat(ret, ",+cov"); + + return ret; + +} + +#endif /* !SIMPLE_FILES */ + + +/* Write a message accompanying the crash directory :-) */ + +static void write_crash_readme(void) { + + u8* fn = alloc_printf("%s/crashes/README.txt", out_dir); + s32 fd; + FILE* f; + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + ck_free(fn); + + /* Do not die on errors here - that would be impolite. */ + + if (fd < 0) return; + + f = fdopen(fd, "w"); + + if (!f) { + close(fd); + return; + } + + fprintf(f, "Command line used to find this crash:\n\n" + + "%s\n\n" + + "If you can't reproduce a bug outside of afl-fuzz, be sure to set the same\n" + "memory limit. The limit used for this fuzzing session was %s.\n\n" + + "Need a tool to minimize test cases before investigating the crashes or sending\n" + "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n" + + "Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop\n" + "me a mail at once the issues are fixed - I'd love to\n" + "add your finds to the gallery at:\n\n" + + " http://lcamtuf.coredump.cx/afl/\n\n" + + "Thanks :-)\n", + + orig_cmdline, DMS(mem_limit << 20)); /* ignore errors */ + + fclose(f); + +} + + +/* Check if the result of an execve() during routine fuzzing is interesting, + save or queue the input test case for further analysis if so. Returns 1 if + entry is saved, 0 otherwise. */ + +static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) { + + u8 *fn = ""; + u8 hnb; + s32 fd; + u8 keeping = 0, res; + + if (fault == crash_mode) { + + /* Keep only if there are new bits in the map, add to queue for + future fuzzing, etc. */ + + if (!(hnb = has_new_bits(virgin_bits))) { + if (crash_mode) total_crashes++; + return 0; + } + + keeping = hnb; + + if(!vaild_flag) { + goto error_check; + } + +#ifndef SIMPLE_FILES + + fn = alloc_printf("%s/queue/id:%06u,%s", out_dir, queued_paths, + describe_op(hnb)); + +#else + + fn = alloc_printf("%s/queue/id_%06u", out_dir, queued_paths); + +#endif /* ^!SIMPLE_FILES */ + + add_to_queue(fn, len, 0); + + if (hnb == 2) { + queue_top->has_new_cov = 1; + queued_with_cov++; + } + + queue_top->exec_cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + + /* Try to calibrate inline; this also calls update_bitmap_score() when + successful. */ + + res = calibrate_case(argv, queue_top, mem, queue_cycle - 1, 0); + + if (res == FAULT_ERROR) + FATAL("Unable to execute target application"); + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_write(fd, mem, len, fn); + close(fd); + } + +error_check: + + switch (fault) { + + case FAULT_TMOUT: + + /* Timeouts are not very interesting, but we're still obliged to keep + a handful of samples. We use the presence of new bits in the + hang-specific bitmap as a signal of uniqueness. In "dumb" mode, we + just keep everything. */ + + total_tmouts++; + + if (unique_hangs >= KEEP_UNIQUE_HANG) return keeping; + + if (!dumb_mode) { + +#ifdef __x86_64__ + simplify_trace((u64*)trace_bits); +#else + simplify_trace((u32*)trace_bits); +#endif /* ^__x86_64__ */ + + if (!has_new_bits(virgin_tmout)) return keeping; + + } + + unique_tmouts++; + + /* Before saving, we make sure that it's a genuine hang by re-running + the target with a more generous timeout (unless the default timeout + is already generous). */ + + if (exec_tmout < hang_tmout) { + + u8 new_fault; + write_to_testcase(mem, len); + new_fault = run_target(argv, hang_tmout); + + /* A corner case that one user reported bumping into: increasing the + timeout actually uncovers a crash. Make sure we don't discard it if + so. */ + + if (!stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash; + + if (stop_soon || new_fault != FAULT_TMOUT) return keeping; + + } + +#ifndef SIMPLE_FILES + + fn = alloc_printf("%s/hangs/id:%06llu,%s", out_dir, + unique_hangs, describe_op(0)); + +#else + + fn = alloc_printf("%s/hangs/id_%06llu", out_dir, + unique_hangs); + +#endif /* ^!SIMPLE_FILES */ + + unique_hangs++; + + last_hang_time = get_cur_time(); + + break; + + case FAULT_CRASH: + +keep_as_crash: + + /* This is handled in a manner roughly similar to timeouts, + except for slightly different limits and no need to re-run test + cases. */ + + total_crashes++; + + if (unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; + + if (!dumb_mode) { + +#ifdef __x86_64__ + simplify_trace((u64*)trace_bits); +#else + simplify_trace((u32*)trace_bits); +#endif /* ^__x86_64__ */ + + if (!has_new_bits(virgin_crash)) return keeping; + + } + + if (!unique_crashes) write_crash_readme(); + +#ifndef SIMPLE_FILES + + fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", out_dir, + unique_crashes, kill_signal, describe_op(0)); + +#else + + fn = alloc_printf("%s/crashes/id_%06llu_%02u", out_dir, unique_crashes, + kill_signal); + +#endif /* ^!SIMPLE_FILES */ + + unique_crashes++; + + last_crash_time = get_cur_time(); + last_crash_execs = total_execs; + + break; + + case FAULT_ERROR: FATAL("Unable to execute target application"); + + default: return keeping; + + } + + /* If we're here, we apparently want to save the crash or hang + test case, too. */ + + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", fn); + ck_write(fd, mem, len, fn); + close(fd); + + ck_free(fn); + + return keeping; + +} + + +/* When resuming, try to find the queue position to start from. This makes sense + only when resuming, and when we can find the original fuzzer_stats. */ + +static u32 find_start_position(void) { + + static u8 tmp[4096]; /* Ought to be enough for anybody. */ + + u8 *fn, *off; + s32 fd, i; + u32 ret; + + if (!resuming_fuzz) return 0; + + if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); + else fn = alloc_printf("%s/../fuzzer_stats", in_dir); + + fd = open(fn, O_RDONLY); + ck_free(fn); + + if (fd < 0) return 0; + + i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ + close(fd); + + off = strstr((const char*)tmp, "cur_path : "); + if (!off) return 0; + + ret = atoi(off + 20); + if (ret >= queued_paths) ret = 0; + return ret; + +} + + +/* The same, but for timeouts. The idea is that when resuming sessions without + -t given, we don't want to keep auto-scaling the timeout over and over + again to prevent it from growing due to random flukes. */ + +static void find_timeout(void) { + + static u8 tmp[4096]; /* Ought to be enough for anybody. */ + + u8 *fn, *off; + s32 fd, i; + u32 ret; + + if (!resuming_fuzz) return; + + if (in_place_resume) fn = alloc_printf("%s/fuzzer_stats", out_dir); + else fn = alloc_printf("%s/../fuzzer_stats", in_dir); + + fd = open(fn, O_RDONLY); + ck_free(fn); + + if (fd < 0) return; + + i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ + close(fd); + + off = strstr((const char*)tmp, "exec_timeout : "); + if (!off) return; + + ret = atoi(off + 20); + if (ret <= 4) return; + + exec_tmout = ret; + timeout_given = 3; + +} + + +/* Update stats file for unattended monitoring. */ + +static void write_stats_file(double bitmap_cvg, double stability, double eps) { + + static double last_bcvg, last_stab, last_eps; + static struct rusage usage; + + u8* fn = alloc_printf("%s/fuzzer_stats", out_dir); + s32 fd; + FILE* f; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + + f = fdopen(fd, "w"); + + if (!f) PFATAL("fdopen() failed"); + + /* Keep last values in case we're called from another context + where exec/sec stats and such are not readily available. */ + + if (!bitmap_cvg && !stability && !eps) { + bitmap_cvg = last_bcvg; + stability = last_stab; + eps = last_eps; + } else { + last_bcvg = bitmap_cvg; + last_stab = stability; + last_eps = eps; + } + + fprintf(f, "start_time : %llu\n" + "last_update : %llu\n" + "fuzzer_pid : %u\n" + "cycles_done : %llu\n" + "execs_done : %llu\n" + "total_vaild : %llu\n" + "execs_per_sec : %0.02f\n" + "paths_total : %u\n" + "paths_favored : %u\n" + "paths_found : %u\n" + "paths_imported : %u\n" + "max_depth : %u\n" + "cur_path : %u\n" /* Must match find_start_position() */ + "pending_favs : %u\n" + "pending_total : %u\n" + "variable_paths : %u\n" + "stability : %0.02f%%\n" + "bitmap_cvg : %0.02f%%\n" + "unique_crashes : %llu\n" + "unique_hangs : %llu\n" + "last_path : %llu\n" + "last_crash : %llu\n" + "last_hang : %llu\n" + "execs_since_crash : %llu\n" + "exec_timeout : %u\n" /* Must match find_timeout() */ + "afl_banner : %s\n" + "afl_version : " VERSION "\n" + "target_mode : %s%s%s%s%s%s%s\n" + "command_line : %s\n" + "slowest_exec_ms : %llu\n", + start_time / 1000, get_cur_time() / 1000, getpid(), + queue_cycle ? (queue_cycle - 1) : 0, total_execs, total_vaild, eps, + queued_paths, queued_favored, queued_discovered, queued_imported, + max_depth, current_entry, pending_favored, pending_not_fuzzed, + queued_variable, stability, bitmap_cvg, unique_crashes, + unique_hangs, last_path_time / 1000, last_crash_time / 1000, + last_hang_time / 1000, total_execs - last_crash_execs, + exec_tmout, use_banner, + qemu_mode ? "qemu " : "", dumb_mode ? " dumb " : "", + no_forkserver ? "no_forksrv " : "", crash_mode ? "crash " : "", + persistent_mode ? "persistent " : "", deferred_mode ? "deferred " : "", + (qemu_mode || dumb_mode || no_forkserver || crash_mode || + persistent_mode || deferred_mode) ? "" : "default", + orig_cmdline, slowest_exec_ms); + + fprintf(f, "mutate total : %llu\n", g_mutator.totalMutate_); + fprintf(f, "mutate failed : %llu\n", g_mutator.failedMutate_); + /* ignore errors */ + /* Get rss value from the children + We must have killed the forkserver process and called waitpid + before calling getrusage */ + if (getrusage(RUSAGE_CHILDREN, &usage)) { + WARNF("getrusage failed"); + } else if (usage.ru_maxrss == 0) { + fprintf(f, "peak_rss_mb : not available while afl is running\n"); + } else { +#ifdef __APPLE__ + fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss >> 20); +#else + fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss >> 10); +#endif /* ^__APPLE__ */ + } + + fclose(f); + +} + + +/* Update the plot file if there is a reason to. */ + +static void maybe_update_plot_file(double bitmap_cvg, double eps) { + + static u32 prev_qp, prev_pf, prev_pnf, prev_ce, prev_md; + static u64 prev_qc, prev_uc, prev_uh; + + if (prev_qp == queued_paths && prev_pf == pending_favored && + prev_pnf == pending_not_fuzzed && prev_ce == current_entry && + prev_qc == queue_cycle && prev_uc == unique_crashes && + prev_uh == unique_hangs && prev_md == max_depth) return; + + prev_qp = queued_paths; + prev_pf = pending_favored; + prev_pnf = pending_not_fuzzed; + prev_ce = current_entry; + prev_qc = queue_cycle; + prev_uc = unique_crashes; + prev_uh = unique_hangs; + prev_md = max_depth; + + /* Fields in the file: + + unix_time, cycles_done, cur_path, paths_total, paths_not_fuzzed, + favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, + execs_per_sec */ + + fprintf(plot_file, + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, %llu, %llu\n", + get_cur_time() / 1000, queue_cycle - 1, current_entry, queued_paths, + pending_not_fuzzed, pending_favored, bitmap_cvg, unique_crashes, + unique_hangs, max_depth, eps, total_execs, total_vaild, seed_count); + + fflush(plot_file); + +} + + + +/* A helper function for maybe_delete_out_dir(), deleting all prefixed + files in a directory. */ + +static u8 delete_files(u8* path, u8* prefix) { + + DIR* d; + struct dirent* d_ent; + + d = opendir(path); + + if (!d) return 0; + + while ((d_ent = readdir(d))) { + + if (d_ent->d_name[0] != '.' && (!prefix || + !strncmp(d_ent->d_name, prefix, strlen(prefix)))) { + + u8* fname = alloc_printf("%s/%s", path, d_ent->d_name); + if (unlink(fname)) PFATAL("Unable to delete '%s'", fname); + ck_free(fname); + + } + + } + + closedir(d); + + return !!rmdir(path); + +} + + +/* Get the number of runnable processes, with some simple smoothing. */ + +static double get_runnable_processes(void) { + + static double res; + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) + + /* I don't see any portable sysctl or so that would quickly give us the + number of runnable processes; the 1-minute load average can be a + semi-decent approximation, though. */ + + if (getloadavg(&res, 1) != 1) return 0; + +#else + + /* On Linux, /proc/stat is probably the best way; load averages are + computed in funny ways and sometimes don't reflect extremely short-lived + processes well. */ + + FILE* f = fopen("/proc/stat", "r"); + u8 tmp[1024]; + u32 val = 0; + + if (!f) return 0; + + while (fgets(tmp, sizeof(tmp), f)) { + + if (!strncmp(tmp, "procs_running ", 14) || + !strncmp(tmp, "procs_blocked ", 14)) val += atoi(tmp + 14); + + } + + fclose(f); + + if (!res) { + + res = val; + + } else { + + res = res * (1.0 - 1.0 / AVG_SMOOTHING) + + ((double)val) * (1.0 / AVG_SMOOTHING); + + } + +#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ + + return res; + +} + + +/* Delete the temporary directory used for in-place session resume. */ + +static void nuke_resume_dir(void) { + + u8* fn; + + fn = alloc_printf("%s/_resume/.state/deterministic_done", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state/auto_extras", out_dir); + if (delete_files(fn, "auto_")) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state/redundant_edges", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state/variable_behavior", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume/.state", out_dir); + if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/_resume", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + return; + +dir_cleanup_failed: + + FATAL("_resume directory cleanup failed"); + +} + + +/* Delete fuzzer output directory if we recognize it as ours, if the fuzzer + is not currently running, and if the last run time isn't too great. */ + +static void maybe_delete_out_dir(void) { + + FILE* f; + u8 *fn = alloc_printf("%s/fuzzer_stats", out_dir); + + /* See if the output directory is locked. If yes, bail out. If not, + create a lock that will persist for the lifetime of the process + (this requires leaving the descriptor open).*/ + + out_dir_fd = open(out_dir, O_RDONLY); + if (out_dir_fd < 0) PFATAL("Unable to open '%s'", out_dir); + +#ifndef __sun + + if (flock(out_dir_fd, LOCK_EX | LOCK_NB) && errno == EWOULDBLOCK) { + + SAYF("\n" cLRD "[-] " cRST + "Looks like the job output directory is being actively used by another\n" + " instance of afl-fuzz. You will need to choose a different %s\n" + " or stop the other process first.\n", + sync_id ? "fuzzer ID" : "output location"); + + FATAL("Directory '%s' is in use", out_dir); + + } + +#endif /* !__sun */ + + f = fopen(fn, "r"); + + if (f) { + + u64 start_time, last_update; + + if (fscanf(f, "start_time : %llu\n" + "last_update : %llu\n", &start_time, &last_update) != 2) + FATAL("Malformed data in '%s'", fn); + + fclose(f); + + /* Let's see how much work is at stake. */ + + if (!in_place_resume && last_update - start_time > OUTPUT_GRACE * 60) { + + SAYF("\n" cLRD "[-] " cRST + "The job output directory already exists and contains the results of more\n" + " than %u minutes worth of fuzzing. To avoid data loss, afl-fuzz will *NOT*\n" + " automatically delete this data for you.\n\n" + + " If you wish to start a new session, remove or rename the directory manually,\n" + " or specify a different output location for this job. To resume the old\n" + " session, put '-' as the input directory in the command line ('-i -') and\n" + " try again.\n", OUTPUT_GRACE); + + FATAL("At-risk data found in '%s'", out_dir); + + } + + } + + ck_free(fn); + + /* The idea for in-place resume is pretty simple: we temporarily move the old + queue/ to a new location that gets deleted once import to the new queue/ + is finished. If _resume/ already exists, the current queue/ may be + incomplete due to an earlier abort, so we want to use the old _resume/ + dir instead, and we let rename() fail silently. */ + + if (in_place_resume) { + + u8* orig_q = alloc_printf("%s/queue", out_dir); + + in_dir = alloc_printf("%s/_resume", out_dir); + + rename(orig_q, in_dir); /* Ignore errors */ + + OKF("Output directory exists, will attempt session resume."); + + ck_free(orig_q); + + } else { + + OKF("Output directory exists but deemed OK to reuse."); + + } + + ACTF("Deleting old session data..."); + + /* Okay, let's get the ball rolling! First, we need to get rid of the entries + in /.synced/.../id:*, if any are present. */ + + if (!in_place_resume) { + + fn = alloc_printf("%s/.synced", out_dir); + if (delete_files(fn, NULL)) goto dir_cleanup_failed; + ck_free(fn); + + } + + /* Next, we need to clean up /queue/.state/ subdirectories: */ + + fn = alloc_printf("%s/queue/.state/deterministic_done", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue/.state/auto_extras", out_dir); + if (delete_files(fn, "auto_")) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue/.state/redundant_edges", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue/.state/variable_behavior", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + /* Then, get rid of the .state subdirectory itself (should be empty by now) + and everything matching /queue/id:*. */ + + fn = alloc_printf("%s/queue/.state", out_dir); + if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/queue", out_dir); + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + /* All right, let's do /crashes/id:* and /hangs/id:*. */ + + if (!in_place_resume) { + + fn = alloc_printf("%s/crashes/README.txt", out_dir); + unlink(fn); /* Ignore errors */ + ck_free(fn); + + } + + fn = alloc_printf("%s/crashes", out_dir); + + /* Make backup of the crashes directory if it's not empty and if we're + doing in-place resume. */ + + if (in_place_resume && rmdir(fn)) { + + time_t cur_t = time(0); + struct tm* t = localtime(&cur_t); + +#ifndef SIMPLE_FILES + + u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#else + + u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#endif /* ^!SIMPLE_FILES */ + + rename(fn, nfn); /* Ignore errors. */ + ck_free(nfn); + + } + + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/hangs", out_dir); + + /* Backup hangs, too. */ + + if (in_place_resume && rmdir(fn)) { + + time_t cur_t = time(0); + struct tm* t = localtime(&cur_t); + +#ifndef SIMPLE_FILES + + u8* nfn = alloc_printf("%s.%04u-%02u-%02u-%02u:%02u:%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#else + + u8* nfn = alloc_printf("%s_%04u%02u%02u%02u%02u%02u", fn, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + +#endif /* ^!SIMPLE_FILES */ + + rename(fn, nfn); /* Ignore errors. */ + ck_free(nfn); + + } + + if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + ck_free(fn); + + /* And now, for some finishing touches. */ + + fn = alloc_printf("%s/.cur_input", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + fn = alloc_printf("%s/fuzz_bitmap", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + if (!in_place_resume) { + fn = alloc_printf("%s/fuzzer_stats", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + } + + fn = alloc_printf("%s/plot_data", out_dir); + if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + ck_free(fn); + + OKF("Output dir cleanup successful."); + + /* Wow... is that all? If yes, celebrate! */ + + return; + +dir_cleanup_failed: + + SAYF("\n" cLRD "[-] " cRST + "Whoops, the fuzzer tried to reuse your output directory, but bumped into\n" + " some files that shouldn't be there or that couldn't be removed - so it\n" + " decided to abort! This happened while processing this path:\n\n" + + " %s\n\n" + " Please examine and manually delete the files, or specify a different\n" + " output location for the tool.\n", fn); + + FATAL("Output directory cleanup failed"); + +} + + +static void check_term_size(void); + + +/* A spiffy retro stats screen! This is called every stats_update_freq + execve() calls, plus in several other circumstances. */ + +static void show_stats(void) { + + static u64 last_stats_ms, last_plot_ms, last_ms, last_execs; + static double avg_exec; + double t_byte_ratio, stab_ratio; + + u64 cur_ms; + u32 t_bytes, t_bits; + + u32 banner_len, banner_pad; + u8 tmp[256]; + + cur_ms = get_cur_time(); + + /* If not enough time has passed since last UI update, bail out. */ + + if (cur_ms - last_ms < 1000 / UI_TARGET_HZ) return; + + /* Check if we're past the 10 minute mark. */ + + if (cur_ms - start_time > 10 * 60 * 1000) run_over10m = 1; + + /* Calculate smoothed exec speed stats. */ + + if (!last_execs) { + + avg_exec = ((double)total_execs) * 1000 / (cur_ms - start_time); + + } else { + + double cur_avg = ((double)(total_execs - last_execs)) * 1000 / + (cur_ms - last_ms); + + /* If there is a dramatic (5x+) jump in speed, reset the indicator + more quickly. */ + + if (cur_avg * 5 < avg_exec || cur_avg / 5 > avg_exec) + avg_exec = cur_avg; + + avg_exec = avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + + cur_avg * (1.0 / AVG_SMOOTHING); + + } + + last_ms = cur_ms; + last_execs = total_execs; + + /* Tell the callers when to contact us (as measured in execs). */ + + stats_update_freq = avg_exec / (UI_TARGET_HZ * 10); + if (!stats_update_freq) stats_update_freq = 1; + + /* Do some bitmap stats. */ + + t_bytes = count_non_255_bytes(virgin_bits); + t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE; + + if (t_bytes) + stab_ratio = 100 - ((double)var_byte_count) * 100 / t_bytes; + else + stab_ratio = 100; + + /* Roughly every minute, update fuzzer stats and save auto tokens. */ + + if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) { + + last_stats_ms = cur_ms; + write_stats_file(t_byte_ratio, stab_ratio, avg_exec); + save_auto(); + write_bitmap(); + + } + + /* Every now and then, write plot data. */ + + if (cur_ms - last_plot_ms > PLOT_UPDATE_SEC * 1000) { + + last_plot_ms = cur_ms; + maybe_update_plot_file(t_byte_ratio, avg_exec); + + } + + /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ + + if (!dumb_mode && cycles_wo_finds > 100 && !pending_not_fuzzed && + getenv("AFL_EXIT_WHEN_DONE")) stop_soon = 2; + + if (total_crashes && getenv("AFL_BENCH_UNTIL_CRASH")) stop_soon = 2; + + /* If we're not on TTY, bail out. */ + + if (not_on_tty) return; + + /* Compute some mildly useful bitmap stats. */ + + t_bits = (MAP_SIZE << 3) - count_bits(virgin_bits); + + /* Now, for the visuals... */ + + if (clear_screen) { + + SAYF(TERM_CLEAR CURSOR_HIDE); + clear_screen = 0; + + check_term_size(); + + } + + SAYF(TERM_HOME); + + if (term_too_small) { + + SAYF(cBRI "Your terminal is too small to display the UI.\n" + "Please resize terminal window to at least 80x25.\n" cRST); + + return; + + } + + /* Let's start by drawing a centered banner. */ + + banner_len = (crash_mode ? 24 : 22) + strlen(VERSION) + strlen(use_banner); + banner_pad = (80 - banner_len) / 2; + memset(tmp, ' ', banner_pad); + + sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN + " (%s)", crash_mode ? cPIN "peruvian were-rabbit" : + cYEL "american fuzzy lop", use_banner); + + SAYF("\n%s\n\n", tmp); + + /* "Handy" shortcuts for drawing boxes... */ + +#define bSTG bSTART cGRA +#define bH2 bH bH +#define bH5 bH2 bH2 bH +#define bH10 bH5 bH5 +#define bH20 bH10 bH10 +#define bH30 bH20 bH10 +#define SP5 " " +#define SP10 SP5 SP5 +#define SP20 SP10 SP10 + + /* Lord, forgive me this. */ + + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH2 bHB + bH bSTOP cCYA " overall results " bSTG bH5 bRT "\n"); + + if (dumb_mode) { + + strcpy(tmp, cRST); + + } else { + + u64 min_wo_finds = (cur_ms - last_path_time) / 1000 / 60; + + /* First queue cycle: don't stop now! */ + if (queue_cycle == 1 || min_wo_finds < 15) strcpy(tmp, cMGN); else + + /* Subsequent cycles, but we're still making finds. */ + if (cycles_wo_finds < 25 || min_wo_finds < 30) strcpy(tmp, cYEL); else + + /* No finds for a long time and no test cases to try. */ + if (cycles_wo_finds > 100 && !pending_not_fuzzed && min_wo_finds > 120) + strcpy(tmp, cLGN); + + /* Default: cautiously OK to stop? */ + else strcpy(tmp, cLBL); + + } + + SAYF(bV bSTOP " run time : " cRST "%-34s " bSTG bV bSTOP + " cycles done : %s%-5s " bSTG bV "\n", + DTD(cur_ms, start_time), tmp, DI(queue_cycle - 1)); + + /* We want to warn people about not seeing new paths after a full cycle, + except when resuming fuzzing or running in non-instrumented mode. */ + + if (!dumb_mode && (last_path_time || resuming_fuzz || queue_cycle == 1 || + in_bitmap || crash_mode)) { + + SAYF(bV bSTOP " last new path : " cRST "%-34s ", + DTD(cur_ms, last_path_time)); + + } else { + + if (dumb_mode) + + SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST + " (non-instrumented mode) "); + + else + + SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD + "(odd, check syntax!) "); + + } + + SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n", + DI(queued_paths)); + + /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH + limit with a '+' appended to the count. */ + + sprintf(tmp, "%s%s", DI(unique_crashes), + (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + SAYF(bV bSTOP " last uniq crash : " cRST "%-34s " bSTG bV bSTOP + " uniq crashes : %s%-6s " bSTG bV "\n", + DTD(cur_ms, last_crash_time), unique_crashes ? cLRD : cRST, + tmp); + + sprintf(tmp, "%s%s", DI(unique_hangs), + (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + + SAYF(bV bSTOP " last uniq hang : " cRST "%-34s " bSTG bV bSTOP + " uniq hangs : " cRST "%-6s " bSTG bV "\n", + DTD(cur_ms, last_hang_time), tmp); + + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH20 bHB bH bSTOP cCYA + " map coverage " bSTG bH bHT bH20 bH2 bH bVL "\n"); + + /* This gets funny because we want to print several variable-length variables + together, but then cram them into a fixed-width field - so we need to + put them in a temporary buffer first. */ + + sprintf(tmp, "%s%s (%0.02f%%)", DI(current_entry), + queue_cur->favored ? "" : "*", + ((double)current_entry * 100) / queued_paths); + + SAYF(bV bSTOP " now processing : " cRST "%-17s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * + 100 / MAP_SIZE, t_byte_ratio); + + SAYF(" map density : %s%-21s " bSTG bV "\n", t_byte_ratio > 70 ? cLRD : + ((t_bytes < 200 && !dumb_mode) ? cPIN : cRST), tmp); + + sprintf(tmp, "%s (%0.02f%%)", DI(cur_skipped_paths), + ((double)cur_skipped_paths * 100) / queued_paths); + + SAYF(bV bSTOP " paths timed out : " cRST "%-17s " bSTG bV, tmp); + + sprintf(tmp, "%0.02f bits/tuple", + t_bytes ? (((double)t_bits) / t_bytes) : 0); + + SAYF(bSTOP " count coverage : " cRST "%-21s " bSTG bV "\n", tmp); + + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH20 bX bH bSTOP cCYA + " findings in depth " bSTG bH20 bVL "\n"); + + /* Yeah... it's still going on... halp? */ + + sprintf(tmp, "%s (%0.02f%%)", DI(total_vaild), + total_execs ? ((double)total_vaild) * 100 / total_execs : (double)0); + + SAYF(bV bSTOP " total vaild : " cRST "%-21s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%s (%0.02f%%)", DI(queued_favored), + ((double)queued_favored) * 100 / queued_paths); + + SAYF(" favored paths : " cRST "%-22s " bSTG bV "\n", tmp); + + if (!stage_max) { + + sprintf(tmp, "%s/-", DI(stage_cur)); + + } else { + + sprintf(tmp, "%s/%s (%0.02f%%)", DI(stage_cur), DI(stage_max), + ((double)stage_cur) * 100 / stage_max); + + } + + SAYF(bV bSTOP " stage execs : " cRST "%-21s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%s (%0.02f%%)", DI(queued_with_cov), + ((double)queued_with_cov) * 100 / queued_paths); + + SAYF(" new edges on : " cRST "%-22s " bSTG bV "\n", tmp); + + sprintf(tmp, "%s (%s%s unique)", DI(total_crashes), DI(unique_crashes), + (unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + if (crash_mode) { + + SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP + " new crashes : %s%-22s " bSTG bV "\n", DI(total_execs), + unique_crashes ? cLRD : cRST, tmp); + + } else { + + SAYF(bV bSTOP " total execs : " cRST "%-21s " bSTG bV bSTOP + " total crashes : %s%-22s " bSTG bV "\n", DI(total_execs), + unique_crashes ? cLRD : cRST, tmp); + + } + + /* Show a warning about slow execution. */ + + if (avg_exec < 100) { + + sprintf(tmp, "%s/sec (%s)", DF(avg_exec), avg_exec < 20 ? + "zzzz..." : "slow!"); + + SAYF(bV bSTOP " exec speed : " cLRD "%-21s ", tmp); + + } else { + + sprintf(tmp, "%s/sec", DF(avg_exec)); + SAYF(bV bSTOP " exec speed : " cRST "%-21s ", tmp); + + } + + sprintf(tmp, "%s (%s%s unique)", DI(total_tmouts), DI(unique_tmouts), + (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + + SAYF (bSTG bV bSTOP " total tmouts : " cRST "%-22s " bSTG bV "\n", tmp); + + /* Aaaalmost there... hold on! */ + + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH bHT bH10 + bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bH bVL "\n"); + + if (skip_deterministic) { + + strcpy(tmp, "n/a, n/a, n/a"); + + } else { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_FLIP1]), DI(stage_cycles[STAGE_FLIP1]), + DI(stage_finds[STAGE_FLIP2]), DI(stage_cycles[STAGE_FLIP2]), + DI(stage_finds[STAGE_FLIP4]), DI(stage_cycles[STAGE_FLIP4])); + + } + + SAYF(bV bSTOP " bit flips : " cRST "%-37s " bSTG bV bSTOP " levels : " + cRST "%-10s " bSTG bV "\n", tmp, DI(max_depth)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_FLIP8]), DI(stage_cycles[STAGE_FLIP8]), + DI(stage_finds[STAGE_FLIP16]), DI(stage_cycles[STAGE_FLIP16]), + DI(stage_finds[STAGE_FLIP32]), DI(stage_cycles[STAGE_FLIP32])); + + SAYF(bV bSTOP " byte flips : " cRST "%-37s " bSTG bV bSTOP " pending : " + cRST "%-10s " bSTG bV "\n", tmp, DI(pending_not_fuzzed)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_ARITH8]), DI(stage_cycles[STAGE_ARITH8]), + DI(stage_finds[STAGE_ARITH16]), DI(stage_cycles[STAGE_ARITH16]), + DI(stage_finds[STAGE_ARITH32]), DI(stage_cycles[STAGE_ARITH32])); + + SAYF(bV bSTOP " arithmetics : " cRST "%-37s " bSTG bV bSTOP " pend fav : " + cRST "%-10s " bSTG bV "\n", tmp, DI(pending_favored)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_INTEREST8]), DI(stage_cycles[STAGE_INTEREST8]), + DI(stage_finds[STAGE_INTEREST16]), DI(stage_cycles[STAGE_INTEREST16]), + DI(stage_finds[STAGE_INTEREST32]), DI(stage_cycles[STAGE_INTEREST32])); + + SAYF(bV bSTOP " known ints : " cRST "%-37s " bSTG bV bSTOP " own finds : " + cRST "%-10s " bSTG bV "\n", tmp, DI(queued_discovered)); + + if (!skip_deterministic) + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + DI(stage_finds[STAGE_EXTRAS_UO]), DI(stage_cycles[STAGE_EXTRAS_UO]), + DI(stage_finds[STAGE_EXTRAS_UI]), DI(stage_cycles[STAGE_EXTRAS_UI]), + DI(stage_finds[STAGE_EXTRAS_AO]), DI(stage_cycles[STAGE_EXTRAS_AO])); + + SAYF(bV bSTOP " dictionary : " cRST "%-37s " bSTG bV bSTOP + " imported : " cRST "%-10s " bSTG bV "\n", tmp, + sync_id ? DI(queued_imported) : (u8*)"n/a"); + + sprintf(tmp, "%s/%s, %s/%s", + DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), + DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE])); + + SAYF(bV bSTOP " havoc : " cRST "%-37s " bSTG bV bSTOP, tmp); + + if (t_bytes) sprintf(tmp, "%0.02f%%", stab_ratio); + else strcpy(tmp, "n/a"); + + SAYF(" stability : %s%-10s " bSTG bV "\n", (stab_ratio < 85 && var_byte_count > 40) + ? cLRD : ((queued_variable && (!persistent_mode || var_byte_count > 20)) + ? cMGN : cRST), tmp); + + if (!bytes_trim_out) { + + sprintf(tmp, "n/a, "); + + } else { + + sprintf(tmp, "%0.02f%%/%s, ", + ((double)(bytes_trim_in - bytes_trim_out)) * 100 / bytes_trim_in, + DI(trim_execs)); + + } + + if (!blocks_eff_total) { + + u8 tmp2[128]; + + sprintf(tmp2, "n/a"); + strcat(tmp, tmp2); + + } else { + + u8 tmp2[128]; + + sprintf(tmp2, "%0.02f%%", + ((double)(blocks_eff_total - blocks_eff_select)) * 100 / + blocks_eff_total); + + strcat(tmp, tmp2); + + } + + SAYF(bV bSTOP " trim : " cRST "%-37s " bSTG bVR bH20 bH2 bH2 bRB "\n" + bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1, tmp); + + /* Provide some CPU utilization stats. */ + + if (cpu_core_count) { + + double cur_runnable = get_runnable_processes(); + u32 cur_utilization = cur_runnable * 100 / cpu_core_count; + + u8* cpu_color = cCYA; + + /* If we could still run one or more processes, use green. */ + + if (cpu_core_count > 1 && cur_runnable + 1 <= cpu_core_count) + cpu_color = cLGN; + + /* If we're clearly oversubscribed, use red. */ + + if (!no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD; + +#ifdef HAVE_AFFINITY + + if (cpu_aff >= 0) { + + SAYF(SP10 cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, + MIN(cpu_aff, 999), cpu_color, + MIN(cur_utilization, 999)); + + } else { + + SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, + cpu_color, MIN(cur_utilization, 999)); + + } + +#else + + SAYF(SP10 cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, + cpu_color, MIN(cur_utilization, 999)); + +#endif /* ^HAVE_AFFINITY */ + + } else SAYF("\r"); + + /* Hallelujah! */ + + fflush(0); + + if (get_cur_time() - last_save_time > 60 * 60 * 1000) { + u8* fn = alloc_printf("%s/coverage_statistics", out_dir); + + FILE* fd = fopen(fn, "a+"); + + if (!fd) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + + fprintf(fd, "%d\t%d\t%d (%0.02f%%)\t%d(%0.02f%%)\n", (unsigned int)((get_cur_time() - start_time) / (60 * 60 * 1000)), queued_paths, total_vaild, total_execs ? ((double)total_vaild) * 100 / total_execs : (double)0, t_bytes, t_byte_ratio); + + fclose(fd); + + last_save_time = get_cur_time(); + } + +} + + +/* Display quick statistics at the end of processing the input directory, + plus a bunch of warnings. Some calibration stuff also ended up here, + along with several hardcoded constants. Maybe clean up eventually. */ + +static void show_init_stats(void) { + + struct queue_entry* q = queue; + u32 min_bits = 0, max_bits = 0; + u64 min_us = 0, max_us = 0; + u64 avg_us = 0; + u32 max_len = 0; + + if (total_cal_cycles) avg_us = total_cal_us / total_cal_cycles; + + while (q) { + + if (!min_us || q->exec_us < min_us) min_us = q->exec_us; + if (q->exec_us > max_us) max_us = q->exec_us; + + if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size; + if (q->bitmap_size > max_bits) max_bits = q->bitmap_size; + + if (q->len > max_len) max_len = q->len; + + q = q->next; + + } + + SAYF("\n"); + + if (avg_us > (qemu_mode ? 50000 : 10000)) + WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.txt.", + doc_path); + + /* Let's keep things moving with slow binaries. */ + + if (avg_us > 50000) havoc_div = 10; /* 0-19 execs/sec */ + else if (avg_us > 20000) havoc_div = 5; /* 20-49 execs/sec */ + else if (avg_us > 10000) havoc_div = 2; /* 50-100 execs/sec */ + + if (!resuming_fuzz) { + + if (max_len > 50 * 1024) + WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.txt!", + DMS(max_len), doc_path); + else if (max_len > 10 * 1024) + WARNF("Some test cases are big (%s) - see %s/perf_tips.txt.", + DMS(max_len), doc_path); + + if (useless_at_start && !in_bitmap) + WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); + + if (queued_paths > 100) + WARNF(cLRD "You probably have far too many input files! Consider trimming down."); + else if (queued_paths > 20) + WARNF("You have lots of input files; try starting small."); + + } + + OKF("Here are some useful stats:\n\n" + + cGRA " Test case count : " cRST "%u favored, %u variable, %u total\n" + cGRA " Bitmap range : " cRST "%u to %u bits (average: %0.02f bits)\n" + cGRA " Exec timing : " cRST "%s to %s us (average: %s us)\n", + queued_favored, queued_variable, queued_paths, min_bits, max_bits, + ((double)total_bitmap_size) / (total_bitmap_entries ? total_bitmap_entries : 1), + DI(min_us), DI(max_us), DI(avg_us)); + + if (!timeout_given) { + + /* Figure out the appropriate timeout. The basic idea is: 5x average or + 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. + + If the program is slow, the multiplier is lowered to 2x or 3x, because + random scheduler jitter is less likely to have any impact, and because + our patience is wearing thin =) */ + + if (avg_us > 50000) exec_tmout = avg_us * 2 / 1000; + else if (avg_us > 10000) exec_tmout = avg_us * 3 / 1000; + else exec_tmout = avg_us * 5 / 1000; + + exec_tmout = MAX(exec_tmout, max_us / 1000); + exec_tmout = (exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; + + if (exec_tmout > EXEC_TIMEOUT) exec_tmout = EXEC_TIMEOUT; + + ACTF("No -t option specified, so I'll use exec timeout of %u ms.", + exec_tmout); + + timeout_given = 1; + + } else if (timeout_given == 3) { + + ACTF("Applying timeout settings from resumed session (%u ms).", exec_tmout); + + } + + /* In dumb mode, re-running every timing out test case with a generous time + limit is very expensive, so let's select a more conservative default. */ + + if (dumb_mode && !getenv("AFL_HANG_TMOUT")) + hang_tmout = MIN(EXEC_TIMEOUT, exec_tmout * 2 + 100); + + OKF("All set and ready to roll!"); + +} + + +/* Find first power of two greater or equal to val (assuming val under + 2^31). */ + +static u32 next_p2(u32 val) { + + u32 ret = 1; + while (val > ret) ret <<= 1; + return ret; + +} + + +/* Trim all new test cases to save cycles when doing deterministic checks. The + trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of + file size, to keep the stage short and sweet. */ + +static u8 trim_case(char** argv, struct queue_entry* q, u8* in_buf) { + + static u8 tmp[64]; + static u8 clean_trace[MAP_SIZE]; + + u8 needs_write = 0, fault = 0; + u32 trim_exec = 0; + u32 remove_len; + u32 len_p2; + + /* Although the trimmer will be less useful when variable behavior is + detected, it will still work to some extent, so we don't check for + this. */ + + if (q->len < 5) return 0; + + stage_name = tmp; + bytes_trim_in += q->len; + + /* Select initial chunk len, starting with large steps. */ + + len_p2 = next_p2(q->len); + + remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES); + + /* Continue until the number of steps gets too high or the stepover + gets too small. */ + + while (remove_len >= MAX(len_p2 / TRIM_END_STEPS, TRIM_MIN_BYTES)) { + + u32 remove_pos = remove_len; + + sprintf(tmp, "trim %s/%s", DI(remove_len), DI(remove_len)); + + stage_cur = 0; + stage_max = q->len / remove_len; + + while (remove_pos < q->len) { + + u32 trim_avail = MIN(remove_len, q->len - remove_pos); + u32 cksum; + + write_with_gap(in_buf, q->len, remove_pos, trim_avail); + + fault = run_target(argv, exec_tmout); + trim_execs++; + + if (stop_soon || fault == FAULT_ERROR) goto abort_trimming; + + /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ + + cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + + /* If the deletion had no impact on the trace, make it permanent. This + isn't perfect for variable-path inputs, but we're just making a + best-effort pass, so it's not a big deal if we end up with false + negatives every now and then. */ + + if (cksum == q->exec_cksum) { + + u32 move_tail = q->len - remove_pos - trim_avail; + + q->len -= trim_avail; + len_p2 = next_p2(q->len); + + memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, + move_tail); + + /* Let's save a clean trace, which will be needed by + update_bitmap_score once we're done with the trimming stuff. */ + + if (!needs_write) { + + needs_write = 1; + memcpy(clean_trace, trace_bits, MAP_SIZE); + + } + + } else remove_pos += remove_len; + + /* Since this can be slow, update the screen every now and then. */ + + if (!(trim_exec++ % stats_update_freq)) show_stats(); + stage_cur++; + + } + + remove_len >>= 1; + + } + + /* If we have made changes to in_buf, we also need to update the on-disk + version of the test case. */ + + if (needs_write) { + + s32 fd; + + unlink(q->fname); /* ignore errors */ + + fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", q->fname); + + ck_write(fd, in_buf, q->len, q->fname); + close(fd); + + memcpy(trace_bits, clean_trace, MAP_SIZE); + update_bitmap_score(q); + + } + +abort_trimming: + + bytes_trim_out += q->len; + return fault; + +} + +int num = 0; +/* Write a modified test case, run program, process results. Handle + error conditions, returning 1 if it's time to bail out. This is + a helper function for fuzz_one(). */ + +EXP_ST u8 common_fuzz_stuff(char** argv, const u8* out_buf, u32 len) { + + u8 fault; + u8 tmp_vaild_flag; + + //cout << num ++ << ":" << out_buf << endl; + if (post_handler) { + + out_buf = post_handler(out_buf, &len); + if (!out_buf || !len) return 0; + + } + write_to_testcase(out_buf, len); + + fault = run_target(argv, exec_tmout); + + tmp_vaild_flag = vaild_flag; + + if (stop_soon) return 1; + + if (fault == FAULT_TMOUT) { + + if (subseq_tmouts++ > TMOUT_LIMIT) { + cur_skipped_paths++; + return 1; + } + + } else subseq_tmouts = 0; + + /* Users can hit us with SIGUSR1 to request the current input + to be abandoned. */ + + if (skip_requested) { + + skip_requested = 0; + cur_skipped_paths++; + return 1; + + } + + /* This handles FAULT_ERROR for us: */ + //cout << num ++ << ":" << out_buf << endl; + int should_keep = save_if_interesting(argv, out_buf, len, fault); + queued_discovered += (should_keep == 1 || should_keep == 2); + + g_mutator.update_status(g_current_input, should_keep, tmp_vaild_flag); + + //cout << "OK" << endl; + if (!(stage_cur % stats_update_freq) || stage_cur + 1 == stage_max) + show_stats(); + + return 0; + +} + + +/* Helper to choose random block len for block operations in fuzz_one(). + Doesn't return zero, provided that max_len is > 0. */ + +static u32 choose_block_len(u32 limit) { + + u32 min_value, max_value; + u32 rlim = MIN(queue_cycle, 3); + + if (!run_over10m) rlim = 1; + + switch (UR(rlim)) { + + case 0: min_value = 1; + max_value = HAVOC_BLK_SMALL; + break; + + case 1: min_value = HAVOC_BLK_SMALL; + max_value = HAVOC_BLK_MEDIUM; + break; + + default: + + if (UR(10)) { + + min_value = HAVOC_BLK_MEDIUM; + max_value = HAVOC_BLK_LARGE; + + } else { + + min_value = HAVOC_BLK_LARGE; + max_value = HAVOC_BLK_XL; + + } + + } + + if (min_value >= limit) min_value = 1; + + return min_value + UR(MIN(max_value, limit) - min_value + 1); + +} + + +/* Calculate case desirability score to adjust the length of havoc fuzzing. + A helper function for fuzz_one(). Maybe some of these constants should + go into config.h. */ + +static u32 calculate_score(struct queue_entry* q) { + + u32 avg_exec_us = total_cal_us / (total_cal_cycles+1); + u32 avg_bitmap_size = total_bitmap_size / (total_bitmap_entries+1); + u32 perf_score = 100; + + /* Adjust score based on execution speed of this path, compared to the + global average. Multiplier ranges from 0.1x to 3x. Fast inputs are + less expensive to fuzz, so we're giving them more air time. */ + + if (q->exec_us * 0.1 > avg_exec_us) perf_score = 10; + else if (q->exec_us * 0.25 > avg_exec_us) perf_score = 25; + else if (q->exec_us * 0.5 > avg_exec_us) perf_score = 50; + else if (q->exec_us * 0.75 > avg_exec_us) perf_score = 75; + else if (q->exec_us * 4 < avg_exec_us) perf_score = 300; + else if (q->exec_us * 3 < avg_exec_us) perf_score = 200; + else if (q->exec_us * 2 < avg_exec_us) perf_score = 150; + + /* Adjust score based on bitmap size. The working theory is that better + coverage translates to better targets. Multiplier from 0.25x to 3x. */ + + if (q->bitmap_size * 0.3 > avg_bitmap_size) perf_score *= 3; + else if (q->bitmap_size * 0.5 > avg_bitmap_size) perf_score *= 2; + else if (q->bitmap_size * 0.75 > avg_bitmap_size) perf_score *= 1.5; + else if (q->bitmap_size * 3 < avg_bitmap_size) perf_score *= 0.25; + else if (q->bitmap_size * 2 < avg_bitmap_size) perf_score *= 0.5; + else if (q->bitmap_size * 1.5 < avg_bitmap_size) perf_score *= 0.75; + + /* Adjust score based on handicap. Handicap is proportional to how late + in the game we learned about this path. Latecomers are allowed to run + for a bit longer until they catch up with the rest. */ + + if (q->handicap >= 4) { + + perf_score *= 4; + q->handicap -= 4; + + } else if (q->handicap) { + + perf_score *= 2; + q->handicap--; + + } + + /* Final adjustment based on input depth, under the assumption that fuzzing + deeper test cases is more likely to reveal stuff that can't be + discovered with traditional fuzzers. */ + + switch (q->depth) { + + case 0 ... 3: break; + case 4 ... 7: perf_score *= 2; break; + case 8 ... 13: perf_score *= 3; break; + case 14 ... 25: perf_score *= 4; break; + default: perf_score *= 5; + + } + + /* Make sure that we don't go over limit. */ + + if (perf_score > HAVOC_MAX_MULT * 100) perf_score = HAVOC_MAX_MULT * 100; + + return perf_score; + +} + + +/* Helper function to see if a particular change (xor_val = old ^ new) could + be a product of deterministic bit flips with the lengths and stepovers + attempted by afl-fuzz. This is used to avoid dupes in some of the + deterministic fuzzing operations that follow bit flips. We also + return 1 if xor_val is zero, which implies that the old and attempted new + values are identical and the exec would be a waste of time. */ + +static u8 could_be_bitflip(u32 xor_val) { + + u32 sh = 0; + + if (!xor_val) return 1; + + /* Shift left until first bit set. */ + + while (!(xor_val & 1)) { sh++; xor_val >>= 1; } + + /* 1-, 2-, and 4-bit patterns are OK anywhere. */ + + if (xor_val == 1 || xor_val == 3 || xor_val == 15) return 1; + + /* 8-, 16-, and 32-bit patterns are OK only if shift factor is + divisible by 8, since that's the stepover for these ops. */ + + if (sh & 7) return 0; + + if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) + return 1; + + return 0; + +} + + +/* Helper function to see if a particular value is reachable through + arithmetic operations. Used for similar purposes. */ + +static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { + + u32 i, ov = 0, nv = 0, diffs = 0; + + if (old_val == new_val) return 1; + + /* See if one-byte adjustments to any byte could produce this result. */ + + for (i = 0; i < blen; i++) { + + u8 a = old_val >> (8 * i), + b = new_val >> (8 * i); + + if (a != b) { diffs++; ov = a; nv = b; } + + } + + /* If only one byte differs and the values are within range, return 1. */ + + if (diffs == 1) { + + if ((u8)(ov - nv) <= ARITH_MAX || + (u8)(nv - ov) <= ARITH_MAX) return 1; + + } + + if (blen == 1) return 0; + + /* See if two-byte adjustments to any byte would produce this result. */ + + diffs = 0; + + for (i = 0; i < blen / 2; i++) { + + u16 a = old_val >> (16 * i), + b = new_val >> (16 * i); + + if (a != b) { diffs++; ov = a; nv = b; } + + } + + /* If only one word differs and the values are within range, return 1. */ + + if (diffs == 1) { + + if ((u16)(ov - nv) <= ARITH_MAX || + (u16)(nv - ov) <= ARITH_MAX) return 1; + + ov = SWAP16(ov); nv = SWAP16(nv); + + if ((u16)(ov - nv) <= ARITH_MAX || + (u16)(nv - ov) <= ARITH_MAX) return 1; + + } + + /* Finally, let's do the same thing for dwords. */ + + if (blen == 4) { + + if ((u32)(old_val - new_val) <= ARITH_MAX || + (u32)(new_val - old_val) <= ARITH_MAX) return 1; + + new_val = SWAP32(new_val); + old_val = SWAP32(old_val); + + if ((u32)(old_val - new_val) <= ARITH_MAX || + (u32)(new_val - old_val) <= ARITH_MAX) return 1; + + } + + return 0; + +} + + + +/* Last but not least, a similar helper to see if insertion of an + interesting integer is redundant given the insertions done for + shorter blen. The last param (check_le) is set if the caller + already executed LE insertion for current blen and wants to see + if BE variant passed in new_val is unique. */ + +static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { + + u32 i, j; + + if (old_val == new_val) return 1; + + /* See if one-byte insertions from interesting_8 over old_val could + produce new_val. */ + + for (i = 0; i < blen; i++) { + + for (j = 0; j < sizeof(interesting_8); j++) { + + u32 tval = (old_val & ~(0xff << (i * 8))) | + (((u8)interesting_8[j]) << (i * 8)); + + if (new_val == tval) return 1; + + } + + } + + /* Bail out unless we're also asked to examine two-byte LE insertions + as a preparation for BE attempts. */ + + if (blen == 2 && !check_le) return 0; + + /* See if two-byte insertions over old_val could give us new_val. */ + + for (i = 0; i < blen - 1; i++) { + + for (j = 0; j < sizeof(interesting_16) / 2; j++) { + + u32 tval = (old_val & ~(0xffff << (i * 8))) | + (((u16)interesting_16[j]) << (i * 8)); + + if (new_val == tval) return 1; + + /* Continue here only if blen > 2. */ + + if (blen > 2) { + + tval = (old_val & ~(0xffff << (i * 8))) | + (SWAP16(interesting_16[j]) << (i * 8)); + + if (new_val == tval) return 1; + + } + + } + + } + + if (blen == 4 && check_le) { + + /* See if four-byte insertions could produce the same result + (LE only). */ + + for (j = 0; j < sizeof(interesting_32) / 4; j++) + if (new_val == (u32)interesting_32[j]) return 1; + + } + + return 0; + +} + + +/* Take the current entry from the queue, fuzz it for a while. This + function is a tad too long... returns 0 if fuzzed successfully, 1 if + skipped or bailed out. */ +//vector ir_set; + +static u8 fuzz_one(char** argv) { + + s32 len, fd, temp_len, i, j; + u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; + u64 havoc_queued, orig_hit_cnt, new_hit_cnt; + u32 splice_cycle = 0, perf_score = 100, orig_perf, prev_cksum, eff_cnt = 1; + u8 ret_val = 1, doing_det = 0; + + u8 a_collect[MAX_AUTO_EXTRA]; + u32 a_len = 0; + + int skip_count = 0; + +#ifdef IGNORE_FINDS + + /* In IGNORE_FINDS mode, skip any entries that weren't in the + initial data set. */ + + if (queue_cur->depth > 1) return 1; + +#else + + if (pending_favored) { + + /* If we have any favored, non-fuzzed new arrivals in the queue, + possibly skip to them at the expense of already-fuzzed or non-favored + cases. */ + + if ((queue_cur->was_fuzzed || !queue_cur->favored) && + UR(100) < SKIP_TO_NEW_PROB) return 1; + + } else if (!dumb_mode && !queue_cur->favored && queued_paths > 10) { + + /* Otherwise, still possibly skip non-favored cases, albeit less often. + The odds of skipping stuff are higher for already-fuzzed inputs and + lower for never-fuzzed entries. */ + + if (queue_cycle > 1 && !queue_cur->was_fuzzed) { + + if (UR(100) < SKIP_NFAV_NEW_PROB) return 1; + + } else { + + if (UR(100) < SKIP_NFAV_OLD_PROB) return 1; + + } + + } + +#endif /* ^IGNORE_FINDS */ + + if (not_on_tty) { + ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", + current_entry, queued_paths, unique_crashes); + fflush(stdout); + } + + /* Map the test case into memory. */ + + fd = open(queue_cur->fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", queue_cur->fname); + + len = queue_cur->len; + + orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + + if (orig_in == MAP_FAILED) PFATAL("Unable to mmap '%s'", queue_cur->fname); + + close(fd); + + out_buf = ck_alloc_nozero(len+1); + + subseq_tmouts = 0; + + cur_depth = queue_cur->depth; + + memcpy(out_buf, in_buf, len); + out_buf[len] = 0; + + orig_perf = perf_score = calculate_score(queue_cur); + + doing_det = 1; + + stage_short = "SQL fuzz"; + stage_max = len << 3; + stage_name = "fuzzing"; + + stage_val_type = STAGE_VAL_NONE; + + orig_hit_cnt = queued_paths + unique_crashes; + + prev_cksum = queue_cur->exec_cksum; + + seed_count++; + + //********************** + + vector mutated_tree = g_mutator.mutate_all((const char*)out_buf); + + stage_max = mutated_tree.size(); + stage_cur = 0; + + for(InputInfo* input: mutated_tree){ + stage_name = "sql_validate"; + + u8* fn = alloc_printf("%s/crash_input", out_dir); + s32 fd; + FILE* f; + + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + + f = fdopen(fd, "w"); + + if (!f) PFATAL("fdopen() failed"); + + fprintf(f, "%s\n", input->input_->to_string().c_str()); + + fclose(f); + + bool tmp_res = g_instantiator.instantaite_sql(input->input_); + + if( tmp_res == false){ + skip_count ++ ; + continue; + } + show_stats(); + string ir_str = input->input_->to_string(); + g_current_input = input; + + char* tmp_str = ir_str.c_str(); + int siz = ir_str.size(); + + stage_name = "sql_fuzz"; + if(common_fuzz_stuff(argv, tmp_str, siz)){ + goto abandon_entry; + } + stage_cur++; + show_stats(); + } + + //********************** + + stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; + stage_cycles[STAGE_FLIP1] += mutated_tree.size() - skip_count; + + + new_hit_cnt = queued_paths + unique_crashes; + + ret_val = 0; + +abandon_entry: + for(InputInfo* input: mutated_tree){ + delete input; + } + + + splicing_with = -1; + + /* Update pending_not_fuzzed count if we made it through the calibration + cycle and have not seen this entry before. */ + + if (!stop_soon && !queue_cur->cal_failed && !queue_cur->was_fuzzed) { + queue_cur->was_fuzzed = 1; + pending_not_fuzzed--; + if (queue_cur->favored) pending_favored--; + } + + munmap(orig_in, queue_cur->len); + + + if (in_buf != orig_in){ ck_free(in_buf);} + + ck_free(out_buf); + ck_free(eff_map); + //ir_set.clear(); + + return ret_val; +} + + +/* Grab interesting test cases from other fuzzers. */ + +static void sync_fuzzers(char** argv) { + + DIR* sd; + struct dirent* sd_ent; + u32 sync_cnt = 0; + + sd = opendir(sync_dir); + if (!sd) PFATAL("Unable to open '%s'", sync_dir); + + stage_max = stage_cur = 0; + cur_depth = 0; + + /* Look at the entries created for every other fuzzer in the sync directory. */ + + while ((sd_ent = readdir(sd))) { + + static u8 stage_tmp[128]; + + DIR* qd; + struct dirent* qd_ent; + u8 *qd_path, *qd_synced_path; + u32 min_accept = 0, next_min_accept; + + s32 id_fd; + + /* Skip dot files and our own output directory. */ + + if (sd_ent->d_name[0] == '.' || !strcmp(sync_id, sd_ent->d_name)) continue; + + /* Skip anything that doesn't have a queue/ subdirectory. */ + + qd_path = alloc_printf("%s/%s/queue", sync_dir, sd_ent->d_name); + + if (!(qd = opendir(qd_path))) { + ck_free(qd_path); + continue; + } + + /* Retrieve the ID of the last seen test case. */ + + qd_synced_path = alloc_printf("%s/.synced/%s", out_dir, sd_ent->d_name); + + id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); + + if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path); + + if (read(id_fd, &min_accept, sizeof(u32)) > 0) + lseek(id_fd, 0, SEEK_SET); + + next_min_accept = min_accept; + + /* Show stats */ + + sprintf(stage_tmp, "sync %u", ++sync_cnt); + stage_name = stage_tmp; + stage_cur = 0; + stage_max = 0; + + /* For every file queued by this fuzzer, parse ID and see if we have looked at + it before; exec a test case if not. */ + + while ((qd_ent = readdir(qd))) { + + u8* path; + s32 fd; + struct stat st; + + if (qd_ent->d_name[0] == '.' || + sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &syncing_case) != 1 || + syncing_case < min_accept) continue; + + /* OK, sounds like a new one. Let's give it a try. */ + + if (syncing_case >= next_min_accept) + next_min_accept = syncing_case + 1; + + path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); + + /* Allow this to fail in case the other fuzzer is resuming or so... */ + + fd = open(path, O_RDONLY); + + if (fd < 0) { + ck_free(path); + continue; + } + + if (fstat(fd, &st)) PFATAL("fstat() failed"); + + /* Ignore zero-sized or oversized files. */ + + if (st.st_size && st.st_size <= MAX_FILE) { + + u8 fault; + u8* mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + + if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path); + + /* See what happens. We rely on save_if_interesting() to catch major + errors and save the test case. */ + + write_to_testcase(mem, st.st_size); + + fault = run_target(argv, exec_tmout); + + if (stop_soon) return; + + syncing_party = sd_ent->d_name; + queued_imported += save_if_interesting(argv, mem, st.st_size, fault); + syncing_party = 0; + + munmap(mem, st.st_size); + + if (!(stage_cur++ % stats_update_freq)) show_stats(); + + } + + ck_free(path); + close(fd); + + } + + ck_write(id_fd, &next_min_accept, sizeof(u32), qd_synced_path); + + close(id_fd); + closedir(qd); + ck_free(qd_path); + ck_free(qd_synced_path); + + } + + closedir(sd); + +} + + +/* Handle stop signal (Ctrl-C, etc). */ + +static void handle_stop_sig(int sig) { + + stop_soon = 1; + + if (child_pid > 0) kill(child_pid, SIGKILL); + if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); + +} + + +/* Handle skip request (SIGUSR1). */ + +static void handle_skipreq(int sig) { + + skip_requested = 1; + +} + +/* Handle timeout (SIGALRM). */ + +static void handle_timeout(int sig) { + + if (child_pid > 0) { + + child_timed_out = 1; + kill(child_pid, SIGKILL); + + } else if (child_pid == -1 && forksrv_pid > 0) { + + child_timed_out = 1; + kill(forksrv_pid, SIGKILL); + + } + +} + + +/* Do a PATH search and find target binary to see that it exists and + isn't a shell script - a common and painful mistake. We also check for + a valid ELF header and for evidence of AFL instrumentation. */ + +EXP_ST void check_binary(u8* fname) { + + u8* env_path = 0; + struct stat st; + + s32 fd; + u8* f_data; + u32 f_len = 0; + + ACTF("Validating target binary..."); + + if (strchr((char *)fname, '/') || !(env_path = getenv("PATH"))) { + + target_path = ck_strdup(fname); + if (stat(target_path, &st) || !S_ISREG(st.st_mode) || + !(st.st_mode & 0111) || (f_len = st.st_size) < 4) + FATAL("Program '%s' not found or not executable", fname); + + } else { + + while (env_path) { + + u8 *cur_elem, *delim = strchr((char *)env_path, ':'); + + if (delim) { + + cur_elem = ck_alloc(delim - env_path + 1); + memcpy(cur_elem, env_path, delim - env_path); + delim++; + + } else cur_elem = ck_strdup(env_path); + + env_path = delim; + + if (cur_elem[0]) + target_path = alloc_printf("%s/%s", cur_elem, fname); + else + target_path = ck_strdup(fname); + + ck_free(cur_elem); + + if (!stat(target_path, &st) && S_ISREG(st.st_mode) && + (st.st_mode & 0111) && (f_len = st.st_size) >= 4) break; + + ck_free(target_path); + target_path = 0; + + } + + if (!target_path) FATAL("Program '%s' not found or not executable", fname); + + } + + if (getenv("AFL_SKIP_BIN_CHECK")) return; + + /* Check for blatant user errors. */ + + if ((!strncmp(target_path, "/tmp/", 5) && !strchr((char *)target_path + 5, '/')) || + (!strncmp(target_path, "/var/tmp/", 9) && !strchr((char *)target_path + 9, '/'))) + FATAL("Please don't keep binaries in /tmp or /var/tmp"); + + fd = open(target_path, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", target_path); + + f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + + if (f_data == MAP_FAILED) PFATAL("Unable to mmap file '%s'", target_path); + + close(fd); + + if (f_data[0] == '#' && f_data[1] == '!') { + + SAYF("\n" cLRD "[-] " cRST + "Oops, the target binary looks like a shell script. Some build systems will\n" + " sometimes generate shell stubs for dynamically linked programs; try static\n" + " library mode (./configure --disable-shared) if that's the case.\n\n" + + " Another possible cause is that you are actually trying to use a shell\n" + " wrapper around the fuzzed component. Invoking shell can slow down the\n" + " fuzzing process by a factor of 20x or more; it's best to write the wrapper\n" + " in a compiled language instead.\n"); + + FATAL("Program '%s' is a shell script", target_path); + + } + +#ifndef __APPLE__ + + if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) + FATAL("Program '%s' is not an ELF binary", target_path); + +#else + + if (f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) + FATAL("Program '%s' is not a 64-bit Mach-O binary", target_path); + +#endif /* ^!__APPLE__ */ + + if (!qemu_mode && !dumb_mode && + !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { + + SAYF("\n" cLRD "[-] " cRST + "Looks like the target binary is not instrumented! The fuzzer depends on\n" + " compile-time instrumentation to isolate interesting test cases while\n" + " mutating the input data. For more information, and for tips on how to\n" + " instrument binaries, please see %s/README.\n\n" + + " When source code is not available, you may be able to leverage QEMU\n" + " mode support. Consult the README for tips on how to enable this.\n" + + " (It is also possible to use afl-fuzz as a traditional, \"dumb\" fuzzer.\n" + " For that, you can use the -n option - but expect much worse results.)\n", + doc_path); + + FATAL("No instrumentation detected"); + + } + + if (qemu_mode && + memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { + + SAYF("\n" cLRD "[-] " cRST + "This program appears to be instrumented with afl-gcc, but is being run in\n" + " QEMU mode (-Q). This is probably not what you want - this setup will be\n" + " slow and offer no practical benefits.\n"); + + FATAL("Instrumentation found in -Q mode"); + + } + + if (memmem(f_data, f_len, "libasan.so", 10) || + memmem(f_data, f_len, "__msan_init", 11)) uses_asan = 1; + + /* Detect persistent & deferred init signatures in the binary. */ + + if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { + + OKF(cPIN "Persistent mode binary detected."); + setenv(PERSIST_ENV_VAR, "1", 1); + persistent_mode = 1; + + } else if (getenv("AFL_PERSISTENT")) { + + WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); + + } + + if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { + + OKF(cPIN "Deferred forkserver binary detected."); + setenv(DEFER_ENV_VAR, "1", 1); + deferred_mode = 1; + + } else if (getenv("AFL_DEFER_FORKSRV")) { + + WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); + + } + + if (munmap(f_data, f_len)) PFATAL("unmap() failed"); + +} + + +/* Trim and possibly create a banner for the run. */ + +static void fix_up_banner(u8* name) { + + if (!use_banner) { + + if (sync_id) { + + use_banner = sync_id; + + } else { + + u8* trim = strrchr((const char*)name, '/'); + if (!trim) use_banner = name; else use_banner = trim + 1; + + } + + } + + if (strlen(use_banner) > 40) { + + u8* tmp = ck_alloc(44); + sprintf(tmp, "%.40s...", use_banner); + use_banner = tmp; + + } + +} + + +/* Check if we're on TTY. */ + +static void check_if_tty(void) { + + struct winsize ws; + + if (getenv("AFL_NO_UI")) { + OKF("Disabling the UI because AFL_NO_UI is set."); + not_on_tty = 1; + return; + } + + if (ioctl(1, TIOCGWINSZ, &ws)) { + + if (errno == ENOTTY) { + OKF("Looks like we're not running on a tty, so I'll be a bit less verbose."); + not_on_tty = 1; + } + + return; + } + +} + + +/* Check terminal dimensions after resize. */ + +static void check_term_size(void) { + + struct winsize ws; + + term_too_small = 0; + + if (ioctl(1, TIOCGWINSZ, &ws)) return; + + if (ws.ws_row < 25 || ws.ws_col < 80) term_too_small = 1; + +} + + + +/* Display usage hints. */ + +static void usage(u8* argv0) { + + SAYF("\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n" + + "Required parameters:\n\n" + + " -i dir - input directory with test cases\n" + " -o dir - output directory for fuzzer findings\n\n" + + "Execution control settings:\n\n" + + " -f file - location read by the fuzzed program (stdin)\n" + " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" + " -m megs - memory limit for child process (%u MB)\n" + " -Q - use binary-only instrumentation (QEMU mode)\n\n" + + "Fuzzing behavior settings:\n\n" + + " -d - quick & dirty mode (skips deterministic steps)\n" + " -n - fuzz without instrumentation (dumb mode)\n" + " -x dir - optional fuzzer dictionary (see README)\n\n" + + "Other stuff:\n\n" + + " -T text - text banner to show on the screen\n" + " -M / -S id - distributed mode (see parallel_fuzzing.txt)\n" + " -C - crash exploration mode (the peruvian rabbit thing)\n\n" + + "For additional tips, please consult %s/README.\n\n", + + argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); + + exit(1); + +} + + +/* Prepare output directories and fds. */ + +EXP_ST void setup_dirs_fds(void) { + + u8* tmp; + s32 fd; + + ACTF("Setting up output directories..."); + + if (sync_id && mkdir(sync_dir, 0700) && errno != EEXIST) + PFATAL("Unable to create '%s'", sync_dir); + + if (mkdir(out_dir, 0700)) { + + if (errno != EEXIST) PFATAL("Unable to create '%s'", out_dir); + + maybe_delete_out_dir(); + + } else { + + if (in_place_resume) + FATAL("Resume attempted but old output directory not found"); + + out_dir_fd = open(out_dir, O_RDONLY); + +#ifndef __sun + + if (out_dir_fd < 0 || flock(out_dir_fd, LOCK_EX | LOCK_NB)) + PFATAL("Unable to flock() output directory."); + +#endif /* !__sun */ + + } + + /* Queue directory for any starting & discovered paths. */ + + tmp = alloc_printf("%s/queue", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Top-level directory for queue metadata used for session + resume and related tasks. */ + + tmp = alloc_printf("%s/queue/.state/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Directory for flagging queue entries that went through + deterministic fuzzing in the past. */ + + tmp = alloc_printf("%s/queue/.state/deterministic_done/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Directory with the auto-selected dictionary entries. */ + + tmp = alloc_printf("%s/queue/.state/auto_extras/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* The set of paths currently deemed redundant. */ + + tmp = alloc_printf("%s/queue/.state/redundant_edges/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* The set of paths showing variable behavior. */ + + tmp = alloc_printf("%s/queue/.state/variable_behavior/", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Sync directory for keeping track of cooperating fuzzers. */ + + if (sync_id) { + + tmp = alloc_printf("%s/.synced/", out_dir); + + if (mkdir(tmp, 0700) && (!in_place_resume || errno != EEXIST)) + PFATAL("Unable to create '%s'", tmp); + + ck_free(tmp); + + } + + /* All recorded crashes. */ + + tmp = alloc_printf("%s/crashes", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* All recorded hangs. */ + + tmp = alloc_printf("%s/hangs", out_dir); + if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + /* Generally useful file descriptors. */ + + dev_null_fd = open("/dev/null", O_RDWR); + if (dev_null_fd < 0) PFATAL("Unable to open /dev/null"); + + dev_urandom_fd = open("/dev/urandom", O_RDONLY); + if (dev_urandom_fd < 0) PFATAL("Unable to open /dev/urandom"); + + /* Gnuplot output file. */ + + tmp = alloc_printf("%s/plot_data", out_dir); + fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) PFATAL("Unable to create '%s'", tmp); + ck_free(tmp); + + plot_file = fdopen(fd, "w"); + if (!plot_file) PFATAL("fdopen() failed"); + + fprintf(plot_file, "# unix_time, cycles_done, cur_path, paths_total, " + "pending_total, pending_favs, map_size, unique_crashes, " + "unique_hangs, max_depth, execs_per_sec, total_execs, total_vaild, seed_count\n"); +} + + +/* Setup the output file for fuzzed data, if not using -f. */ + +EXP_ST void setup_stdio_file(void) { + + u8* fn = alloc_printf("%s/.cur_input", out_dir); + + unlink(fn); /* Ignore errors */ + + out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600); + + if (out_fd < 0) PFATAL("Unable to create '%s'", fn); + + ck_free(fn); + +} + + +/* Make sure that core dumps don't go to a program. */ + +static void check_crash_handling(void) { + +#ifdef __APPLE__ + + /* Yuck! There appears to be no simple C API to query for the state of + loaded daemons on MacOS X, and I'm a bit hesitant to do something + more sophisticated, such as disabling crash reporting via Mach ports, + until I get a box to test the code. So, for now, we check for crash + reporting the awful way. */ + + if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return; + + SAYF("\n" cLRD "[-] " cRST + "Whoops, your system is configured to forward crash notifications to an\n" + " external crash reporting utility. This will cause issues due to the\n" + " extended delay between the fuzzed binary malfunctioning and this fact\n" + " being relayed to the fuzzer via the standard waitpid() API.\n\n" + " To avoid having crashes misinterpreted as timeouts, please run the\n" + " following commands:\n\n" + + " SL=/System/Library; PL=com.apple.ReportCrash\n" + " launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n" + " sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n"); + + if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) + FATAL("Crash reporter detected"); + +#else + + /* This is Linux specific, but I don't think there's anything equivalent on + *BSD, so we can just let it slide for now. */ + + s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY); + u8 fchar; + + if (fd < 0) return; + + ACTF("Checking core_pattern..."); + + /*if (read(fd, &fchar, 1) == 1 && fchar == '|') { + + SAYF("\n" cLRD "[-] " cRST + "Hmm, your system is configured to send core dump notifications to an\n" + " external utility. This will cause issues: there will be an extended delay\n" + " between stumbling upon a crash and having this information relayed to the\n" + " fuzzer via the standard waitpid() API.\n\n" + + " To avoid having crashes misinterpreted as timeouts, please log in as root\n" + " and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" + + " echo core >/proc/sys/kernel/core_pattern\n"); + + if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) + FATAL("Pipe at the beginning of 'core_pattern'"); + + }*/ + + close(fd); + +#endif /* ^__APPLE__ */ + +} + + +/* Check CPU governor. */ + +static void check_cpu_governor(void) { + + FILE* f; + u8 tmp[128]; + u64 min = 0, max = 0; + + if (getenv("AFL_SKIP_CPUFREQ")) return; + + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r"); + if (!f) return; + + ACTF("Checking CPU scaling governor..."); + + if (!fgets(tmp, 128, f)) PFATAL("fgets() failed"); + + fclose(f); + + if (!strncmp(tmp, "perf", 4)) return; + + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r"); + + if (f) { + if (fscanf(f, "%llu", &min) != 1) min = 0; + fclose(f); + } + + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r"); + + if (f) { + if (fscanf(f, "%llu", &max) != 1) max = 0; + fclose(f); + } + + if (min == max) return; + + SAYF("\n" cLRD "[-] " cRST + "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" + " between %llu and %llu MHz. Unfortunately, the scaling algorithm in the\n" + " kernel is imperfect and can miss the short-lived processes spawned by\n" + " afl-fuzz. To keep things moving, run these commands as root:\n\n" + + " cd /sys/devices/system/cpu\n" + " echo performance | tee cpu*/cpufreq/scaling_governor\n\n" + + " You can later go back to the original state by replacing 'performance' with\n" + " 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ\n" + " to make afl-fuzz skip this check - but expect some performance drop.\n", + min / 1024, max / 1024); + + FATAL("Suboptimal CPU scaling governor"); + +} + + +/* Count the number of logical CPU cores. */ + +static void get_core_count(void) { + + u32 cur_runnable = 0; + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) + + size_t s = sizeof(cpu_core_count); + + /* On *BSD systems, we can just use a sysctl to get the number of CPUs. */ + +#ifdef __APPLE__ + + if (sysctlbyname("hw.logicalcpu", &cpu_core_count, &s, NULL, 0) < 0) + return; + +#else + + int s_name[2] = { CTL_HW, HW_NCPU }; + + if (sysctl(s_name, 2, &cpu_core_count, &s, NULL, 0) < 0) return; + +#endif /* ^__APPLE__ */ + +#else + +#ifdef HAVE_AFFINITY + + cpu_core_count = sysconf(_SC_NPROCESSORS_ONLN); + +#else + + FILE* f = fopen("/proc/stat", "r"); + u8 tmp[1024]; + + if (!f) return; + + while (fgets(tmp, sizeof(tmp), f)) + if (!strncmp(tmp, "cpu", 3) && isdigit(tmp[3])) cpu_core_count++; + + fclose(f); + +#endif /* ^HAVE_AFFINITY */ + +#endif /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */ + + if (cpu_core_count > 0) { + + cur_runnable = (u32)get_runnable_processes(); + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) + + /* Add ourselves, since the 1-minute average doesn't include that yet. */ + + cur_runnable++; + +#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ + + OKF("You have %u CPU core%s and %u runnable tasks (utilization: %0.0f%%).", + cpu_core_count, cpu_core_count > 1 ? "s" : "", + cur_runnable, cur_runnable * 100.0 / cpu_core_count); + + if (cpu_core_count > 1) { + + if (cur_runnable > cpu_core_count * 1.5) { + + WARNF("System under apparent load, performance may be spotty."); + + } else if (cur_runnable + 1 <= cpu_core_count) { + + OKF("Try parallel jobs - see %s/parallel_fuzzing.txt.", doc_path); + + } + + } + + } else { + + cpu_core_count = 0; + WARNF("Unable to figure out the number of CPU cores."); + + } + +} + + +/* Validate and fix up out_dir and sync_dir when using -S. */ + +static void fix_up_sync(void) { + + u8* x = sync_id; + + if (dumb_mode) + FATAL("-S / -M and -n are mutually exclusive"); + + if (skip_deterministic) { + + if (force_deterministic) + FATAL("use -S instead of -M -d"); + else + FATAL("-S already implies -d"); + + } + + while (*x) { + + if (!isalnum(*x) && *x != '_' && *x != '-') + FATAL("Non-alphanumeric fuzzer ID specified via -S or -M"); + + x++; + + } + + if (strlen(sync_id) > 32) FATAL("Fuzzer ID too long"); + + x = alloc_printf("%s/%s", out_dir, sync_id); + + sync_dir = out_dir; + out_dir = x; + + if (!force_deterministic) { + skip_deterministic = 1; + use_splicing = 1; + } + +} + + +/* Handle screen resize (SIGWINCH). */ + +static void handle_resize(int sig) { + clear_screen = 1; +} + + +/* Check ASAN options. */ + +static void check_asan_opts(void) { + u8* x = getenv("ASAN_OPTIONS"); + + if (x) { + + if (!strstr((char *)x, "abort_on_error=1")) + FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); + + if (!strstr((char *)x, "symbolize=0")) + FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); + + } + + x = getenv("MSAN_OPTIONS"); + + if (x) { + + if (!strstr((char *)x, "exit_code=" STRINGIFY(MSAN_ERROR))) + FATAL("Custom MSAN_OPTIONS set without exit_code=" + STRINGIFY(MSAN_ERROR) " - please fix!"); + + if (!strstr((char *)x, "symbolize=0")) + FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); + + } + +} + + +/* Detect @@ in args. */ + +EXP_ST void detect_file_args(char** argv) { + + u32 i = 0; + u8* cwd = getcwd(NULL, 0); + + if (!cwd) PFATAL("getcwd() failed"); + + while (argv[i]) { + + u8* aa_loc = strstr((const char*)argv[i], "@@"); + + if (aa_loc) { + + u8 *aa_subst, *n_arg; + + /* If we don't have a file name chosen yet, use a safe default. */ + + if (!out_file) + out_file = alloc_printf("%s/.cur_input", out_dir); + + /* Be sure that we're always using fully-qualified paths. */ + + if (out_file[0] == '/') aa_subst = out_file; + else aa_subst = alloc_printf("%s/%s", cwd, out_file); + + /* Construct a replacement argv value. */ + + *aa_loc = 0; + n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); + argv[i] = n_arg; + *aa_loc = '@'; + + if (out_file[0] != '/') ck_free(aa_subst); + + } + + i++; + + } + + free(cwd); /* not tracked */ + +} + + +/* Set up signal handlers. More complicated that needs to be, because libc on + Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call + siginterrupt(), and does other unnecessary things. */ + +EXP_ST void setup_signal_handlers(void) { + + struct sigaction sa; + + sa.sa_handler = NULL; + sa.sa_flags = SA_RESTART; + sa.sa_sigaction = NULL; + + sigemptyset(&sa.sa_mask); + + /* Various ways of saying "stop". */ + + sa.sa_handler = handle_stop_sig; + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + /* Exec timeout notifications. */ + + sa.sa_handler = handle_timeout; + sigaction(SIGALRM, &sa, NULL); + + /* Window resize */ + + sa.sa_handler = handle_resize; + sigaction(SIGWINCH, &sa, NULL); + + /* SIGUSR1: skip entry */ + + sa.sa_handler = handle_skipreq; + sigaction(SIGUSR1, &sa, NULL); + + /* Things we don't care about. */ + + sa.sa_handler = SIG_IGN; + sigaction(SIGTSTP, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + +} + + +/* Rewrite argv for QEMU. */ + +static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { + + char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); + u8 *tmp, *cp, *rsl, *own_copy; + + /* Workaround for a QEMU stability glitch. */ + + setenv("QEMU_LOG", "nochain", 1); + + memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); + + new_argv[2] = target_path; + new_argv[1] = "--"; + + /* Now we need to actually find the QEMU binary to put in argv[0]. */ + + tmp = getenv("AFL_PATH"); + + if (tmp) { + + cp = alloc_printf("%s/afl-qemu-trace", tmp); + + if (access(cp, X_OK)) + FATAL("Unable to find '%s'", tmp); + + target_path = new_argv[0] = cp; + return new_argv; + + } + + own_copy = ck_strdup(own_loc); + rsl = strrchr((const char*)own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + cp = alloc_printf("%s/afl-qemu-trace", own_copy); + ck_free(own_copy); + + if (!access(cp, X_OK)) { + + target_path = new_argv[0] = cp; + return new_argv; + + } + + } else ck_free(own_copy); + + if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { + + target_path = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); + return new_argv; + + } + + SAYF("\n" cLRD "[-] " cRST + "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be built\n" + " separately by following the instructions in qemu_mode/README.qemu. If you\n" + " already have the binary installed, you may need to specify AFL_PATH in the\n" + " environment.\n\n" + + " Of course, even without QEMU, afl-fuzz can still work with binaries that are\n" + " instrumented at compile time with afl-gcc. It is also possible to use it as a\n" + " traditional \"dumb\" fuzzer by specifying '-n' in the command line.\n"); + + FATAL("Failed to locate 'afl-qemu-trace'."); + +} + + +/* Make a copy of the current command line. */ + +static void save_cmdline(u32 argc, char** argv) { + + u32 len = 1, i; + u8* buf; + + for (i = 0; i < argc; i++) + len += strlen(argv[i]) + 1; + + buf = orig_cmdline = ck_alloc(len); + + for (i = 0; i < argc; i++) { + + u32 l = strlen(argv[i]); + + memcpy(buf, argv[i], l); + buf += l; + + if (i != argc - 1) *(buf++) = ' '; + + } + + *buf = 0; + +} + +#ifndef AFL_LIB + +char* g_server_path; +char* g_client_path; + +int main(int argc, char** argv) { + s32 opt; + u64 prev_queued = 0; + u32 sync_interval_cnt = 0, seek_to; + u8 *extras_dir = 0; + u8 mem_limit_given = 0; + u8 exit_1 = !!getenv("AFL_BENCH_JUST_ONE"); + char** use_argv; + + struct timeval tv; + struct timezone tz; + memset_fucking_array(); + SAYF(cCYA "SQLFuzzer " cBRI VERSION cRST " by hackers\n");//string_lib he common_string_lib YOUSHENME QUBIE + + doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; + + gettimeofday(&tv, &tz); + srandom(tv.tv_sec ^ tv.tv_usec ^ getpid()); + + while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q:s:c:")) > 0) + + switch (opt) { + case 'i': /* input dir */ + + if (in_dir) FATAL("Multiple -i options not supported"); + in_dir = optarg; + + if (!strcmp(in_dir, "-")) in_place_resume = 1; + + break; + + case 's': /* server's path */ + if (g_server_path) FATAL("Multiple -s options not supported"); + g_server_path = optarg; + break; + + case 'o': /* output dir */ + + if (out_dir) FATAL("Multiple -o options not supported"); + out_dir = optarg; + break; + + case 'M': { /* master sync ID */ + + u8* c; + + if (sync_id) FATAL("Multiple -S or -M options not supported"); + sync_id = ck_strdup(optarg); + + if ((c = strchr((char *)sync_id, ':'))) { + + *c = 0; + + if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 || + !master_id || !master_max || master_id > master_max || + master_max > 1000000) FATAL("Bogus master ID passed to -M"); + + } + + force_deterministic = 1; + + } + + break; + + case 'S': + + if (sync_id) FATAL("Multiple -S or -M options not supported"); + sync_id = ck_strdup(optarg); + break; + + case 'f': /* target file */ + + if (out_file) FATAL("Multiple -f options not supported"); + out_file = optarg; + break; + + case 'x': /* dictionary */ + + if (extras_dir) FATAL("Multiple -x options not supported"); + extras_dir = optarg; + break; + + case 't': { /* timeout */ + + u8 suffix = 0; + + if (timeout_given) FATAL("Multiple -t options not supported"); + + if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 || + optarg[0] == '-') FATAL("Bad syntax used for -t"); + + if (exec_tmout < 5) FATAL("Dangerously low value of -t"); + + if (suffix == '+') timeout_given = 2; else timeout_given = 1; + + break; + + } + + case 'm': { /* mem limit */ + + u8 suffix = 'M'; + + if (mem_limit_given) FATAL("Multiple -m options not supported"); + mem_limit_given = 1; + + if (!strcmp(optarg, "none")) { + + mem_limit = 0; + break; + + } + + if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || + optarg[0] == '-') FATAL("Bad syntax used for -m"); + + switch (suffix) { + + case 'T': mem_limit *= 1024 * 1024; break; + case 'G': mem_limit *= 1024; break; + case 'k': mem_limit /= 1024; break; + case 'M': break; + + default: FATAL("Unsupported suffix or bad syntax for -m"); + + } + + if (mem_limit < 5) FATAL("Dangerously low value of -m"); + + if (sizeof(rlim_t) == 4 && mem_limit > 2000) + FATAL("Value of -m out of range on 32-bit systems"); + + } + + break; + + case 'd': /* skip deterministic */ + + if (skip_deterministic) FATAL("Multiple -d options not supported"); + skip_deterministic = 1; + use_splicing = 1; + break; + + case 'B': /* load bitmap */ + + /* This is a secret undocumented option! It is useful if you find + an interesting test case during a normal fuzzing process, and want + to mutate it without rediscovering any of the test cases already + found during an earlier run. + + To use this mode, you need to point -B to the fuzz_bitmap produced + by an earlier run for the exact same binary... and that's it. + + I only used this once or twice to get variants of a particular + file, so I'm not making this an official setting. */ + + if (in_bitmap) FATAL("Multiple -B options not supported"); + + in_bitmap = optarg; + read_bitmap(in_bitmap); + break; + + case 'C': /* crash mode */ + + if (crash_mode) FATAL("Multiple -C options not supported"); + crash_mode = FAULT_CRASH; + break; + + case 'n': /* dumb mode */ + + if (dumb_mode) FATAL("Multiple -n options not supported"); + if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1; + + break; + + case 'T': /* banner */ + + if (use_banner) FATAL("Multiple -T options not supported"); + use_banner = optarg; + break; + + case 'Q': /* QEMU mode */ + + if (qemu_mode) FATAL("Multiple -Q options not supported"); + qemu_mode = 1; + + if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; + + break; + + default: + + usage(argv[0]); + + } + + if (optind == argc || !in_dir || !out_dir) usage(argv[0]); + + setup_signal_handlers(); + check_asan_opts(); + + if (sync_id) fix_up_sync(); + + if (!strcmp(in_dir, out_dir)) + FATAL("Input and output directories can't be the same"); + + if (dumb_mode) { + + if (crash_mode) FATAL("-C and -n are mutually exclusive"); + if (qemu_mode) FATAL("-Q and -n are mutually exclusive"); + + } + + no_forkserver = 1; + if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1; + if (getenv("AFL_NO_ARITH")) no_arith = 1; + if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1; + if (getenv("AFL_FAST_CAL")) fast_cal = 1; + + if (getenv("AFL_HANG_TMOUT")) { + hang_tmout = atoi(getenv("AFL_HANG_TMOUT")); + if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); + } + + if (dumb_mode == 2 && no_forkserver) + FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); + + if (getenv("AFL_PRELOAD")) { + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); + setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); + } + + if (getenv("AFL_LD_PRELOAD")) + FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); + + save_cmdline(argc, argv); + + fix_up_banner(argv[optind]); + + check_if_tty(); + + get_core_count(); + + #ifdef HAVE_AFFINITY + bind_to_free_cpu(); + #endif /* HAVE_AFFINITY */ + //check_crash_handling(); + check_cpu_governor(); + + setup_post(); + setup_shm(); + init_count_class16(); + + setup_dirs_fds(); + read_testcases(); + load_auto(); + + pivot_inputs(); + + if (extras_dir) load_extras(extras_dir); + + if (!timeout_given) find_timeout(); + + detect_file_args(argv + optind + 1); + + if (!out_file) setup_stdio_file(); + + //check_binary(argv[optind]); + //check_binary(g_server_path); + + start_time = get_cur_time(); + last_save_time = start_time; + + if (qemu_mode) + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + else + use_argv = argv + optind; + + g_mutator.init_IR_library(INIT_LIB); + g_mutator.init_IR_config_info(GRAMMAR_INFORMATION); + + g_connector.close_db(); + g_connector.start_db(file, options); + + //char* tmp_argv[] = {g_server_path, NULL}; + //init_forkserver(tmp_argv); + // to do + perform_dry_run(use_argv); + + cull_queue(); + + show_init_stats(); + + seek_to = find_start_position(); + + write_stats_file(0, 0, 0); + save_auto(); + + if (stop_soon) goto stop_fuzzing; + + /* Woop woop woop */ + + if (!not_on_tty) { + sleep(4); + start_time += 4000; + if (stop_soon) goto stop_fuzzing; + } + + //reboot_server(0x1000000);//start server before we fuzz + while (1) { + + u8 skipped_fuzz; + + cull_queue(); + + if (!queue_cur) { + + queue_cycle++; + current_entry = 0; + cur_skipped_paths = 0; + queue_cur = queue; + + while (seek_to) { + current_entry++; + seek_to--; + queue_cur = queue_cur->next; + } + + show_stats(); + + if (not_on_tty) { + ACTF("Entering queue cycle %llu.", queue_cycle); + fflush(stdout); + } + + /* If we had a full queue cycle with no new finds, try + recombination strategies next. */ + + if (queued_paths == prev_queued) { + + if (use_splicing) cycles_wo_finds++; else use_splicing = 1; + + } else cycles_wo_finds = 0; + + prev_queued = queued_paths; + + if (sync_id && queue_cycle == 1 && getenv("AFL_IMPORT_FIRST")) + sync_fuzzers(use_argv); + + } + + skipped_fuzz = fuzz_one(use_argv); + + if (!stop_soon && sync_id && !skipped_fuzz) { + + if (!(sync_interval_cnt++ % SYNC_INTERVAL)) + sync_fuzzers(use_argv); + + } + + if (!stop_soon && exit_1) stop_soon = 2; + + if (stop_soon) break; + + queue_cur = queue_cur->next; + current_entry++; + } + + if (queue_cur) show_stats(); + + write_bitmap(); + write_stats_file(0, 0, 0); + save_auto(); + +stop_fuzzing: + + SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, + stop_soon == 2 ? "programmatically" : "by user"); + + /* Running for more than 30 minutes but still doing first cycle? */ + + if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) { + + SAYF("\n" cYEL "[!] " cRST + "Stopped during the first cycle, results may be incomplete.\n" + " (For info on resuming, see %s/README.)\n", doc_path); + + } + + //g_mutator.print_information(OUTPUT_PATH); + g_connector.close_db(); + + fclose(plot_file); + destroy_queue(); + destroy_extras(); + ck_free(target_path); + ck_free(sync_id); + + alloc_report(); + + OKF("We're done here. Have a nice day!\n"); + + exit(0); + +} + +#endif /* !AFL_LIB */ diff --git a/AFL/alloc-inl.h b/AFL/alloc-inl.h new file mode 100755 index 0000000..9a68126 --- /dev/null +++ b/AFL/alloc-inl.h @@ -0,0 +1,577 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - error-checking, memory-zeroing alloc routines + ------------------------------------------------------------------ + + Written and maintained by Michal Zalewski + + This allocator is not designed to resist malicious attackers (the canaries + are small and predictable), but provides a robust and portable way to detect + use-after-free, off-by-one writes, stale pointers, and so on. +*/ + +#ifndef _HAVE_ALLOC_INL_H +#define _HAVE_ALLOC_INL_H + +#include +#include +#include + +#include "config.h" +#include "types.h" +#include "debug.h" + +/* User-facing macro to sprintf() to a dynamically allocated buffer. */ + +#define alloc_printf(_str...) ({ \ + u8* _tmp; \ + s32 _len = snprintf(NULL, 0, _str); \ + if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \ + _tmp = ck_alloc(_len + 1); \ + snprintf((char*)_tmp, _len + 1, _str); \ + _tmp; \ + }) + +/* Macro to enforce allocation limits as a last-resort defense against + integer overflows. */ + +#define ALLOC_CHECK_SIZE(_s) do { \ + if ((_s) > MAX_ALLOC) \ + ABORT("Bad alloc request: %u bytes", (_s)); \ + } while (0) + +/* Macro to check malloc() failures and the like. */ + +#define ALLOC_CHECK_RESULT(_r, _s) do { \ + if (!(_r)) \ + ABORT("Out of memory: can't allocate %u bytes", (_s)); \ + } while (0) + +/* Magic tokens used to mark used / freed chunks. */ + +#define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ +#define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ +#define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */ + +/* Positions of guard tokens in relation to the user-visible pointer. */ + +#define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) +#define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) +#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) + +#define ALLOC_OFF_HEAD 8 +#define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) + +/* Allocator increments for ck_realloc_block(). */ + +#define ALLOC_BLK_INC 256 + +/* Sanity-checking macros for pointers. */ + +#define CHECK_PTR(_p) do { \ + if (_p) { \ + if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ + if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ + ABORT("Use after free."); \ + else ABORT("Corrupted head alloc canary."); \ + } \ + if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ + ABORT("Corrupted tail alloc canary."); \ + } \ + } while (0) + +#define CHECK_PTR_EXPR(_p) ({ \ + typeof (_p) _tmp = (_p); \ + CHECK_PTR(_tmp); \ + _tmp; \ + }) + + +/* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized + requests. */ + +static inline void* DFL_ck_alloc_nozero(u32 size) { + + void* ret; + + if (!size) return NULL; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + return ret; + +} + + +/* Allocate a buffer, returning zeroed memory. */ + +static inline void* DFL_ck_alloc(u32 size) { + + void* mem; + + if (!size) return NULL; + mem = DFL_ck_alloc_nozero(size); + + return memset(mem, 0, size); + +} + + +/* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD + is set, the old memory will be also clobbered with 0xFF. */ + +static inline void DFL_ck_free(void* mem) { + + if (!mem) return; + + CHECK_PTR(mem); + +#ifdef DEBUG_BUILD + + /* Catch pointer issues sooner. */ + memset(mem, 0xFF, ALLOC_S(mem)); + +#endif /* DEBUG_BUILD */ + + ALLOC_C1(mem) = ALLOC_MAGIC_F; + + free(mem - ALLOC_OFF_HEAD); + +} + + +/* Re-allocate a buffer, checking for issues and zeroing any newly-added tail. + With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the + old memory is clobbered with 0xFF. */ + +static inline void* DFL_ck_realloc(void* orig, u32 size) { + + void* ret; + u32 old_size = 0; + + if (!size) { + + DFL_ck_free(orig); + return NULL; + + } + + if (orig) { + + CHECK_PTR(orig); + +#ifndef DEBUG_BUILD + ALLOC_C1(orig) = ALLOC_MAGIC_F; +#endif /* !DEBUG_BUILD */ + + old_size = ALLOC_S(orig); + orig -= ALLOC_OFF_HEAD; + + ALLOC_CHECK_SIZE(old_size); + + } + + ALLOC_CHECK_SIZE(size); + +#ifndef DEBUG_BUILD + + ret = realloc(orig, size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + +#else + + /* Catch pointer issues sooner: force relocation and make sure that the + original buffer is wiped. */ + + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + if (orig) { + + memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); + memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); + + ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; + + free(orig); + + } + +#endif /* ^!DEBUG_BUILD */ + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + if (size > old_size) + memset(ret + old_size, 0, size - old_size); + + return ret; + +} + + +/* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up + repeated small reallocs without complicating the user code). */ + +static inline void* DFL_ck_realloc_block(void* orig, u32 size) { + +#ifndef DEBUG_BUILD + + if (orig) { + + CHECK_PTR(orig); + + if (ALLOC_S(orig) >= size) return orig; + + size += ALLOC_BLK_INC; + + } + +#endif /* !DEBUG_BUILD */ + + return DFL_ck_realloc(orig, size); + +} + + +/* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */ + +static inline u8* DFL_ck_strdup(u8* str) { + + void* ret; + u32 size; + + if (!str) return NULL; + + size = strlen((char*)str) + 1; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + return memcpy(ret, str, size); + +} + + +/* Create a buffer with a copy of a memory block. Returns NULL for zero-sized + or NULL inputs. */ + +static inline void* DFL_ck_memdup(void* mem, u32 size) { + + void* ret; + + if (!mem || !size) return NULL; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + return memcpy(ret, mem, size); + +} + + +/* Create a buffer with a block of text, appending a NUL terminator at the end. + Returns NULL for zero-sized or NULL inputs. */ + +static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { + + u8* ret; + + if (!mem || !size) return NULL; + + ALLOC_CHECK_SIZE(size); + ret = malloc(size + ALLOC_OFF_TOTAL + 1); + ALLOC_CHECK_RESULT(ret, size); + + ret += ALLOC_OFF_HEAD; + + ALLOC_C1(ret) = ALLOC_MAGIC_C1; + ALLOC_S(ret) = size; + ALLOC_C2(ret) = ALLOC_MAGIC_C2; + + memcpy(ret, mem, size); + ret[size] = 0; + + return ret; + +} + + +#ifndef DEBUG_BUILD + +/* In non-debug mode, we just do straightforward aliasing of the above functions + to user-visible names such as ck_alloc(). */ + +#define ck_alloc DFL_ck_alloc +#define ck_alloc_nozero DFL_ck_alloc_nozero +#define ck_realloc DFL_ck_realloc +#define ck_realloc_block DFL_ck_realloc_block +#define ck_strdup DFL_ck_strdup +#define ck_memdup DFL_ck_memdup +#define ck_memdup_str DFL_ck_memdup_str +#define ck_free DFL_ck_free + +#define alloc_report() + +#else + +/* In debugging mode, we also track allocations to detect memory leaks, and the + flow goes through one more layer of indirection. */ + +/* Alloc tracking data structures: */ + +#define ALLOC_BUCKETS 4096 + +struct TRK_obj { + void *ptr; + char *file, *func; + u32 line; +}; + +#ifdef AFL_MAIN + +struct TRK_obj* TRK[ALLOC_BUCKETS]; +u32 TRK_cnt[ALLOC_BUCKETS]; + +# define alloc_report() TRK_report() + +#else + +extern struct TRK_obj* TRK[ALLOC_BUCKETS]; +extern u32 TRK_cnt[ALLOC_BUCKETS]; + +# define alloc_report() + +#endif /* ^AFL_MAIN */ + +/* Bucket-assigning function for a given pointer: */ + +#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) + + +/* Add a new entry to the list of allocated objects. */ + +static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, + u32 line) { + + u32 i, bucket; + + if (!ptr) return; + + bucket = TRKH(ptr); + + /* Find a free slot in the list of entries for that bucket. */ + + for (i = 0; i < TRK_cnt[bucket]; i++) + + if (!TRK[bucket][i].ptr) { + + TRK[bucket][i].ptr = ptr; + TRK[bucket][i].file = (char*)file; + TRK[bucket][i].func = (char*)func; + TRK[bucket][i].line = line; + return; + + } + + /* No space available - allocate more. */ + + TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], + (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); + + TRK[bucket][i].ptr = ptr; + TRK[bucket][i].file = (char*)file; + TRK[bucket][i].func = (char*)func; + TRK[bucket][i].line = line; + + TRK_cnt[bucket]++; + +} + + +/* Remove entry from the list of allocated objects. */ + +static inline void TRK_free_buf(void* ptr, const char* file, const char* func, + u32 line) { + + u32 i, bucket; + + if (!ptr) return; + + bucket = TRKH(ptr); + + /* Find the element on the list... */ + + for (i = 0; i < TRK_cnt[bucket]; i++) + + if (TRK[bucket][i].ptr == ptr) { + + TRK[bucket][i].ptr = 0; + return; + + } + + WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", + func, file, line); + +} + + +/* Do a final report on all non-deallocated objects. */ + +static inline void TRK_report(void) { + + u32 i, bucket; + + fflush(0); + + for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) + for (i = 0; i < TRK_cnt[bucket]; i++) + if (TRK[bucket][i].ptr) + WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", + TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); + +} + + +/* Simple wrappers for non-debugging functions: */ + +static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, + u32 line) { + + void* ret = DFL_ck_alloc(size); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_realloc(orig, size); + TRK_free_buf(orig, file, func, line); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_realloc_block(orig, size); + TRK_free_buf(orig, file, func, line); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, + u32 line) { + + void* ret = DFL_ck_strdup(str); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_memdup(mem, size); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, + const char* func, u32 line) { + + void* ret = DFL_ck_memdup_str(mem, size); + TRK_alloc_buf(ret, file, func, line); + return ret; + +} + + +static inline void TRK_ck_free(void* ptr, const char* file, + const char* func, u32 line) { + + TRK_free_buf(ptr, file, func, line); + DFL_ck_free(ptr); + +} + +/* Aliasing user-facing names to tracking functions: */ + +#define ck_alloc(_p1) \ + TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) + +#define ck_alloc_nozero(_p1) \ + TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) + +#define ck_realloc(_p1, _p2) \ + TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_realloc_block(_p1, _p2) \ + TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_strdup(_p1) \ + TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) + +#define ck_memdup(_p1, _p2) \ + TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_memdup_str(_p1, _p2) \ + TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) + +#define ck_free(_p1) \ + TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) + +#endif /* ^!DEBUG_BUILD */ + +#endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/AFL/config.h b/AFL/config.h new file mode 100755 index 0000000..52fc352 --- /dev/null +++ b/AFL/config.h @@ -0,0 +1,357 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - vaguely configurable bits + ---------------------------------------------- + + Written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_CONFIG_H +#define _HAVE_CONFIG_H + +#include "types.h" + +/* Version string: */ + +#define VERSION "2.56b" + +/****************************************************** + * * + * Settings that may be of interest to power users: * + * * + ******************************************************/ + +/* Comment out to disable terminal colors (note that this makes afl-analyze + a lot less nice): */ + +#define USE_COLOR + +/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ + +#define FANCY_BOXES + +/* Default timeout for fuzzed code (milliseconds). This is the upper bound, + also used for detecting hangs; the actual value is auto-scaled: */ + +#define EXEC_TIMEOUT 1000 + +/* Timeout rounding factor when auto-scaling (milliseconds): */ + +#define EXEC_TM_ROUND 20 + +/* Default memory limit for child process (MB): */ + +#ifndef __x86_64__ +# define MEM_LIMIT 25 +#else +# define MEM_LIMIT 50 +#endif /* ^!__x86_64__ */ + +/* Default memory limit when running in QEMU mode (MB): */ + +#define MEM_LIMIT_QEMU 200 + +/* Number of calibration cycles per every new test case (and for test + cases that show variable behavior): */ + +#define CAL_CYCLES 8 +#define CAL_CYCLES_LONG 40 + +/* Number of subsequent timeouts before abandoning an input file: */ + +#define TMOUT_LIMIT 250 + +/* Maximum number of unique hangs or crashes to record: */ + +#define KEEP_UNIQUE_HANG 500 +#define KEEP_UNIQUE_CRASH 5000 + +/* Baseline number of random tweaks during a single 'havoc' stage: */ + +#define HAVOC_CYCLES 256 +#define HAVOC_CYCLES_INIT 1024 + +/* Maximum multiplier for the above (should be a power of two, beware + of 32-bit int overflows): */ + +#define HAVOC_MAX_MULT 16 + +/* Absolute minimum number of havoc cycles (after all adjustments): */ + +#define HAVOC_MIN 16 + +/* Maximum stacking for havoc-stage tweaks. The actual value is calculated + like this: + + n = random between 1 and HAVOC_STACK_POW2 + stacking = 2^n + + In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or + 128 stacked tweaks: */ + +#define HAVOC_STACK_POW2 7 + +/* Caps on block sizes for cloning and deletion operations. Each of these + ranges has a 33% probability of getting picked, except for the first + two cycles where smaller blocks are favored: */ + +#define HAVOC_BLK_SMALL 32 +#define HAVOC_BLK_MEDIUM 128 +#define HAVOC_BLK_LARGE 1500 + +/* Extra-large blocks, selected very rarely (<5% of the time): */ + +#define HAVOC_BLK_XL 32768 + +/* Probabilities of skipping non-favored entries in the queue, expressed as + percentages: */ + +#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ +#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ +#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ + +/* Splicing cycle count: */ + +#define SPLICE_CYCLES 15 + +/* Nominal per-splice havoc cycle length: */ + +#define SPLICE_HAVOC 32 + +/* Maximum offset for integer addition / subtraction stages: */ + +#define ARITH_MAX 35 + +/* Limits for the test case trimmer. The absolute minimum chunk size; and + the starting and ending divisors for chopping up the input file: */ + +#define TRIM_MIN_BYTES 4 +#define TRIM_START_STEPS 16 +#define TRIM_END_STEPS 1024 + +/* Maximum size of input file, in bytes (keep under 100MB): */ + +#define MAX_FILE (1 * 1024 * 1024) + +/* The same, for the test case minimizer: */ + +#define TMIN_MAX_FILE (10 * 1024 * 1024) + +/* Block normalization steps for afl-tmin: */ + +#define TMIN_SET_MIN_SIZE 4 +#define TMIN_SET_STEPS 128 + +/* Maximum dictionary token size (-x), in bytes: */ + +#define MAX_DICT_FILE 128 + +/* Length limits for auto-detected dictionary tokens: */ + +#define MIN_AUTO_EXTRA 3 +#define MAX_AUTO_EXTRA 32 + +/* Maximum number of user-specified dictionary tokens to use in deterministic + steps; past this point, the "extras/user" step will be still carried out, + but with proportionally lower odds: */ + +#define MAX_DET_EXTRAS 200 + +/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing + (first value), and to keep in memory as candidates. The latter should be much + higher than the former. */ + +#define USE_AUTO_EXTRAS 50 +#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) + +/* Scaling factor for the effector map used to skip some of the more + expensive deterministic steps. The actual divisor is set to + 2^EFF_MAP_SCALE2 bytes: */ + +#define EFF_MAP_SCALE2 3 + +/* Minimum input file length at which the effector logic kicks in: */ + +#define EFF_MIN_LEN 128 + +/* Maximum effector density past which everything is just fuzzed + unconditionally (%): */ + +#define EFF_MAX_PERC 90 + +/* UI refresh frequency (Hz): */ + +#define UI_TARGET_HZ 5 + +/* Fuzzer stats file and plot update intervals (sec): */ + +#define STATS_UPDATE_SEC 60 +#define PLOT_UPDATE_SEC 5 + +/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ + +#define AVG_SMOOTHING 16 + +/* Sync interval (every n havoc cycles): */ + +#define SYNC_INTERVAL 5 + +/* Output directory reuse grace period (minutes): */ + +#define OUTPUT_GRACE 25 + +/* Uncomment to use simple file names (id_NNNNNN): */ + +// #define SIMPLE_FILES + +/* List of interesting values to use in fuzzing. */ + +#define INTERESTING_8 \ + -128, /* Overflow signed 8-bit when decremented */ \ + -1, /* */ \ + 0, /* */ \ + 1, /* */ \ + 16, /* One-off with common buffer size */ \ + 32, /* One-off with common buffer size */ \ + 64, /* One-off with common buffer size */ \ + 100, /* One-off with common buffer size */ \ + 127 /* Overflow signed 8-bit when incremented */ + +#define INTERESTING_16 \ + -32768, /* Overflow signed 16-bit when decremented */ \ + -129, /* Overflow signed 8-bit */ \ + 128, /* Overflow signed 8-bit */ \ + 255, /* Overflow unsig 8-bit when incremented */ \ + 256, /* Overflow unsig 8-bit */ \ + 512, /* One-off with common buffer size */ \ + 1000, /* One-off with common buffer size */ \ + 1024, /* One-off with common buffer size */ \ + 4096, /* One-off with common buffer size */ \ + 32767 /* Overflow signed 16-bit when incremented */ + +#define INTERESTING_32 \ + -2147483648LL, /* Overflow signed 32-bit when decremented */ \ + -100663046, /* Large negative number (endian-agnostic) */ \ + -32769, /* Overflow signed 16-bit */ \ + 32768, /* Overflow signed 16-bit */ \ + 65535, /* Overflow unsig 16-bit when incremented */ \ + 65536, /* Overflow unsig 16 bit */ \ + 100663045, /* Large positive number (endian-agnostic) */ \ + 2147483647 /* Overflow signed 32-bit when incremented */ + +/*********************************************************** + * * + * Really exotic stuff you probably don't want to touch: * + * * + ***********************************************************/ + +/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ + +#define RESEED_RNG 10000 + +/* Maximum line length passed from GCC to 'as' and used for parsing + configuration files: */ + +#define MAX_LINE 8192 + +/* Environment variable used to pass SHM ID to the called program. */ + +#define SHM_ENV_VAR "__AFL_SHM_ID" + +/* Other less interesting, internal-only variables. */ + +#define CLANG_ENV_VAR "__AFL_CLANG_MODE" +#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" +#define PERSIST_ENV_VAR "__AFL_PERSISTENT" +#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" + +/* In-code signatures for deferred and persistent mode. */ + +#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" +#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" + +/* Distinctive bitmap signature used to indicate failed execution: */ + +#define EXEC_FAIL_SIG 0xfee1dead + +/* Distinctive exit code used to indicate MSAN trip condition: */ + +#define MSAN_ERROR 86 + +/* Designated file descriptors for forkserver commands (the application will + use FORKSRV_FD and FORKSRV_FD + 1): */ + +#define FORKSRV_FD 198 + +/* Fork server init timeout multiplier: we'll wait the user-selected + timeout plus this much for the fork server to spin up. */ + +#define FORK_WAIT_MULT 10 + +/* Calibration timeout adjustments, to be a bit more generous when resuming + fuzzing sessions or trying to calibrate already-added internal finds. + The first value is a percentage, the other is in milliseconds: */ + +#define CAL_TMOUT_PERC 125 +#define CAL_TMOUT_ADD 50 + +/* Number of chances to calibrate a case before giving up: */ + +#define CAL_CHANCES 3 + +/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than + 2; you probably want to keep it under 18 or so for performance reasons + (adjusting AFL_INST_RATIO when compiling is probably a better way to solve + problems with complex programs). You need to recompile the target binary + after changing this - otherwise, SEGVs may ensue. */ + +#define MAP_SIZE_POW2 18 +#define MAP_SIZE (1 << MAP_SIZE_POW2) + +/* Maximum allocator request size (keep well under INT_MAX): */ + +#define MAX_ALLOC 0x40000000 + +/* A made-up hashing seed: */ + +#define HASH_CONST 0xa5b35705 + +/* Constants for afl-gotcpu to control busy loop timing: */ + +#define CTEST_TARGET_MS 5000 +#define CTEST_CORE_TRG_MS 1000 +#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) + +/* Uncomment this to use inferior block-coverage-based instrumentation. Note + that you need to recompile the target binary for this to have any effect: */ + +// #define COVERAGE_ONLY + +/* Uncomment this to ignore hit counts and output just one bit per tuple. + As with the previous setting, you will need to recompile the target + binary: */ + +// #define SKIP_COUNTS + +/* Uncomment this to use instrumentation data to record newly discovered paths, + but do not use them as seeds for fuzzing. This is useful for conveniently + measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ + +// #define IGNORE_FINDS + +#endif /* ! _HAVE_CONFIG_H */ diff --git a/AFL/debug.h b/AFL/debug.h new file mode 100755 index 0000000..5f75974 --- /dev/null +++ b/AFL/debug.h @@ -0,0 +1,258 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - debug / error handling macros + -------------------------------------------------- + + Written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_DEBUG_H +#define _HAVE_DEBUG_H + +#include + +#include "types.h" +#include "config.h" + +/******************* + * Terminal colors * + *******************/ + +#ifdef USE_COLOR + +# define cBLK "\x1b[0;30m" +# define cRED "\x1b[0;31m" +# define cGRN "\x1b[0;32m" +# define cBRN "\x1b[0;33m" +# define cBLU "\x1b[0;34m" +# define cMGN "\x1b[0;35m" +# define cCYA "\x1b[0;36m" +# define cLGR "\x1b[0;37m" +# define cGRA "\x1b[1;90m" +# define cLRD "\x1b[1;91m" +# define cLGN "\x1b[1;92m" +# define cYEL "\x1b[1;93m" +# define cLBL "\x1b[1;94m" +# define cPIN "\x1b[1;95m" +# define cLCY "\x1b[1;96m" +# define cBRI "\x1b[1;97m" +# define cRST "\x1b[0m" + +# define bgBLK "\x1b[40m" +# define bgRED "\x1b[41m" +# define bgGRN "\x1b[42m" +# define bgBRN "\x1b[43m" +# define bgBLU "\x1b[44m" +# define bgMGN "\x1b[45m" +# define bgCYA "\x1b[46m" +# define bgLGR "\x1b[47m" +# define bgGRA "\x1b[100m" +# define bgLRD "\x1b[101m" +# define bgLGN "\x1b[102m" +# define bgYEL "\x1b[103m" +# define bgLBL "\x1b[104m" +# define bgPIN "\x1b[105m" +# define bgLCY "\x1b[106m" +# define bgBRI "\x1b[107m" + +#else + +# define cBLK "" +# define cRED "" +# define cGRN "" +# define cBRN "" +# define cBLU "" +# define cMGN "" +# define cCYA "" +# define cLGR "" +# define cGRA "" +# define cLRD "" +# define cLGN "" +# define cYEL "" +# define cLBL "" +# define cPIN "" +# define cLCY "" +# define cBRI "" +# define cRST "" + +# define bgBLK "" +# define bgRED "" +# define bgGRN "" +# define bgBRN "" +# define bgBLU "" +# define bgMGN "" +# define bgCYA "" +# define bgLGR "" +# define bgGRA "" +# define bgLRD "" +# define bgLGN "" +# define bgYEL "" +# define bgLBL "" +# define bgPIN "" +# define bgLCY "" +# define bgBRI "" + +#endif /* ^USE_COLOR */ + +/************************* + * Box drawing sequences * + *************************/ + +#ifdef FANCY_BOXES + +# define SET_G1 "\x1b)0" /* Set G1 for box drawing */ +# define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ +# define bSTART "\x0e" /* Enter G1 drawing mode */ +# define bSTOP "\x0f" /* Leave G1 drawing mode */ +# define bH "q" /* Horizontal line */ +# define bV "x" /* Vertical line */ +# define bLT "l" /* Left top corner */ +# define bRT "k" /* Right top corner */ +# define bLB "m" /* Left bottom corner */ +# define bRB "j" /* Right bottom corner */ +# define bX "n" /* Cross */ +# define bVR "t" /* Vertical, branch right */ +# define bVL "u" /* Vertical, branch left */ +# define bHT "v" /* Horizontal, branch top */ +# define bHB "w" /* Horizontal, branch bottom */ + +#else + +# define SET_G1 "" +# define RESET_G1 "" +# define bSTART "" +# define bSTOP "" +# define bH "-" +# define bV "|" +# define bLT "+" +# define bRT "+" +# define bLB "+" +# define bRB "+" +# define bX "+" +# define bVR "+" +# define bVL "+" +# define bHT "+" +# define bHB "+" + +#endif /* ^FANCY_BOXES */ + +/*********************** + * Misc terminal codes * + ***********************/ + +#define TERM_HOME "\x1b[H" +#define TERM_CLEAR TERM_HOME "\x1b[2J" +#define cEOL "\x1b[0K" +#define CURSOR_HIDE "\x1b[?25l" +#define CURSOR_SHOW "\x1b[?25h" + +/************************ + * Debug & error macros * + ************************/ + +/* Just print stuff to the appropriate stream. */ + +#ifdef MESSAGES_TO_STDOUT +# define SAYF(x...) printf(x) +#else +# define SAYF(x...) fprintf(stderr, x) +#endif /* ^MESSAGES_TO_STDOUT */ + +/* Show a prefixed warning. */ + +#define WARNF(x...) do { \ + SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Show a prefixed "doing something" message. */ + +#define ACTF(x...) do { \ + SAYF(cLBL "[*] " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Show a prefixed "success" message. */ + +#define OKF(x...) do { \ + SAYF(cLGN "[+] " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Show a prefixed fatal error message (not used in afl). */ + +#define BADF(x...) do { \ + SAYF(cLRD "\n[-] " cRST x); \ + SAYF(cRST "\n"); \ + } while (0) + +/* Die with a verbose non-OS fatal error message. */ + +#define FATAL(x...) do { \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ + cBRI x); \ + SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + exit(1); \ + } while (0) + +/* Die by calling abort() to provide a core dump. */ + +#define ABORT(x...) do { \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ + cBRI x); \ + SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + abort(); \ + } while (0) + +/* Die while also including the output of perror(). */ + +#define PFATAL(x...) do { \ + fflush(stdout); \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \ + cBRI x); \ + SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ + exit(1); \ + } while (0) + +/* Die with FAULT() or PFAULT() depending on the value of res (used to + interpret different failure modes for read(), write(), etc). */ + +#define RPFATAL(res, x...) do { \ + if (res < 0) PFATAL(x); else FATAL(x); \ + } while (0) + +/* Error-checking versions of read() and write() that call RPFATAL() as + appropriate. */ + +#define ck_write(fd, buf, len, fn) do { \ + u32 _len = (len); \ + s32 _res = write(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ + } while (0) + +#define ck_read(fd, buf, len, fn) do { \ + u32 _len = (len); \ + s32 _res = read(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ + } while (0) + +#endif /* ! _HAVE_DEBUG_H */ diff --git a/AFL/hash.h b/AFL/hash.h new file mode 100755 index 0000000..e17fc8f --- /dev/null +++ b/AFL/hash.h @@ -0,0 +1,111 @@ +/* + Copyright 2016 Google LLC All rights reserved. + + 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. +*/ + +/* + american fuzzy lop - hashing function + ------------------------------------- + + The hash32() function is a variant of MurmurHash3, a good + non-cryptosafe hashing function developed by Austin Appleby. + + For simplicity, this variant does *NOT* accept buffer lengths + that are not divisible by 8 bytes. The 32-bit version is otherwise + similar to the original; the 64-bit one is a custom hack with + mostly-unproven properties. + + Austin's original code is public domain. + + Other code written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_HASH_H +#define _HAVE_HASH_H + +#include "types.h" + +#ifdef __x86_64__ + +#define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) + +static inline u32 hash32(const void* key, u32 len, u32 seed) { + + const u64* data = (u64*)key; + u64 h1 = seed ^ len; + + len >>= 3; + + while (len--) { + + u64 k1 = *data++; + + k1 *= 0x87c37b91114253d5ULL; + k1 = ROL64(k1, 31); + k1 *= 0x4cf5ad432745937fULL; + + h1 ^= k1; + h1 = ROL64(h1, 27); + h1 = h1 * 5 + 0x52dce729; + + } + + h1 ^= h1 >> 33; + h1 *= 0xff51afd7ed558ccdULL; + h1 ^= h1 >> 33; + h1 *= 0xc4ceb9fe1a85ec53ULL; + h1 ^= h1 >> 33; + + return h1; + +} + +#else + +#define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) + +static inline u32 hash32(const void* key, u32 len, u32 seed) { + + const u32* data = (u32*)key; + u32 h1 = seed ^ len; + + len >>= 2; + + while (len--) { + + u32 k1 = *data++; + + k1 *= 0xcc9e2d51; + k1 = ROL32(k1, 15); + k1 *= 0x1b873593; + + h1 ^= k1; + h1 = ROL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + + } + + h1 ^= h1 >> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >> 16; + + return h1; + +} + +#endif /* ^__x86_64__ */ + +#endif /* !_HAVE_HASH_H */ diff --git a/AFL/types.h b/AFL/types.h new file mode 100755 index 0000000..f4a5716 --- /dev/null +++ b/AFL/types.h @@ -0,0 +1,94 @@ +/* + Copyright 2013 Google LLC All rights reserved. + + 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. +*/ + + +/* + american fuzzy lop - type definitions and minor macros + ------------------------------------------------------ + + Written and maintained by Michal Zalewski +*/ + +#ifndef _HAVE_TYPES_H +#define _HAVE_TYPES_H + +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +/* + + Ugh. There is an unintended compiler / glibc #include glitch caused by + combining the u64 type an %llu in format strings, necessitating a workaround. + + In essence, the compiler is always looking for 'unsigned long long' for %llu. + On 32-bit systems, the u64 type (aliased to uint64_t) is expanded to + 'unsigned long long' in , so everything checks out. + + But on 64-bit systems, it is #ifdef'ed in the same file as 'unsigned long'. + Now, it only happens in circumstances where the type happens to have the + expected bit width, *but* the compiler does not know that... and complains + about 'unsigned long' being unsafe to pass to %llu. + + */ + +#ifdef __x86_64__ +typedef unsigned long long u64; +#else +typedef uint64_t u64; +#endif /* ^__x86_64__ */ + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +#ifndef MIN +# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) +# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) +#endif /* !MIN */ + +#define SWAP16(_x) ({ \ + u16 _ret = (_x); \ + (u16)((_ret << 8) | (_ret >> 8)); \ + }) + +#define SWAP32(_x) ({ \ + u32 _ret = (_x); \ + (u32)((_ret << 24) | (_ret >> 24) | \ + ((_ret << 8) & 0x00FF0000) | \ + ((_ret >> 8) & 0x0000FF00)); \ + }) + +#ifdef AFL_LLVM_PASS +# define AFL_R(x) (random() % (x)) +#else +# define R(x) (random() % (x)) +#endif /* ^AFL_LLVM_PASS */ + +#define STRINGIFY_INTERNAL(x) #x +#define STRINGIFY(x) STRINGIFY_INTERNAL(x) + +#define MEM_BARRIER() \ + __asm__ volatile("" ::: "memory") + +#define likely(_x) __builtin_expect(!!(_x), 1) +#define unlikely(_x) __builtin_expect(!!(_x), 0) + +#endif /* ! _HAVE_TYPES_H */ -- Gitee