autogenerate fuzzing data from spec (#95)
This commit is contained in:
parent
59819690ec
commit
bf1f56547c
@ -1,90 +1,152 @@
|
||||
"MD5"
|
||||
"SHA1"
|
||||
"SHA256"
|
||||
"__restart"
|
||||
"accessType"
|
||||
"accessTypes"
|
||||
"adapterData"
|
||||
"adapterID"
|
||||
"additionalModuleColumns"
|
||||
"address"
|
||||
"addressRange"
|
||||
"algorithm"
|
||||
"all"
|
||||
"allThreadsContinued"
|
||||
"allThreadsStopped"
|
||||
"allowPartial"
|
||||
"always"
|
||||
"areas"
|
||||
"args"
|
||||
"argsCanBeInterpretedByShell"
|
||||
"arguments"
|
||||
"attach"
|
||||
"attachForSuspendedLaunch"
|
||||
"attributeName"
|
||||
"attributes"
|
||||
"baseClass"
|
||||
"body"
|
||||
"boolean"
|
||||
"breakMode"
|
||||
"breakpoint"
|
||||
"breakpointLocations"
|
||||
"breakpoints"
|
||||
"bytesWritten"
|
||||
"canPersist"
|
||||
"canRestart"
|
||||
"cancel"
|
||||
"cancellable"
|
||||
"cancelled"
|
||||
"capabilities"
|
||||
"category"
|
||||
"changed"
|
||||
"checksum"
|
||||
"checksums"
|
||||
"class"
|
||||
"clientID"
|
||||
"clientName"
|
||||
"clipboard"
|
||||
"color"
|
||||
"column"
|
||||
"columnsStartAt1"
|
||||
"command"
|
||||
"completions"
|
||||
"completionTriggerCharacters"
|
||||
"completions"
|
||||
"condition"
|
||||
"conditionDescription"
|
||||
"configuration"
|
||||
"configurationDone"
|
||||
"console"
|
||||
"constructor"
|
||||
"content"
|
||||
"context"
|
||||
"continue"
|
||||
"continued"
|
||||
"count"
|
||||
"customcolor"
|
||||
"cwd"
|
||||
"data"
|
||||
"data breakpoint"
|
||||
"dataBreakpoint"
|
||||
"dataBreakpointInfo"
|
||||
"dataId"
|
||||
"dateTimeStamp"
|
||||
"deemphasize"
|
||||
"default"
|
||||
"description"
|
||||
"detail"
|
||||
"details"
|
||||
"disassemble"
|
||||
"disconnect"
|
||||
"emphasize"
|
||||
"end"
|
||||
"endColumn"
|
||||
"endLine"
|
||||
"entry"
|
||||
"enum"
|
||||
"env"
|
||||
"error"
|
||||
"evaluate"
|
||||
"evaluateName"
|
||||
"event"
|
||||
"exception"
|
||||
"exceptionBreakpointFilters"
|
||||
"exceptionId"
|
||||
"exceptionInfo"
|
||||
"exceptionOptions"
|
||||
"exitCode"
|
||||
"exited"
|
||||
"expensive"
|
||||
"expression"
|
||||
"expression"
|
||||
"filter"
|
||||
"external"
|
||||
"field"
|
||||
"file"
|
||||
"filter"
|
||||
"filterId"
|
||||
"filterOptions"
|
||||
"filters"
|
||||
"final"
|
||||
"format"
|
||||
"frameId"
|
||||
"fullTypeName"
|
||||
"function"
|
||||
"function breakpoint"
|
||||
"goto"
|
||||
"gotoTargets"
|
||||
"granularity"
|
||||
"group"
|
||||
"hex"
|
||||
"hitBreakpointIds"
|
||||
"hitCondition"
|
||||
"hover"
|
||||
"id"
|
||||
"important"
|
||||
"includeAll"
|
||||
"indexed"
|
||||
"indexedVariables"
|
||||
"indexedVariables"
|
||||
"initialize"
|
||||
"initialized"
|
||||
"innerClass"
|
||||
"innerException"
|
||||
"instruction"
|
||||
"instruction breakpoint"
|
||||
"instructionBytes"
|
||||
"instructionCount"
|
||||
"instructionOffset"
|
||||
"instructionPointerReference"
|
||||
"instructionReference"
|
||||
"instructions"
|
||||
"integrated"
|
||||
"interface"
|
||||
"internal"
|
||||
"invalidated"
|
||||
"isLocalProcess"
|
||||
"isOptimized"
|
||||
"isUserCode"
|
||||
"keyword"
|
||||
"kind"
|
||||
"label"
|
||||
"launch"
|
||||
"lazy"
|
||||
"length"
|
||||
"levels"
|
||||
"line"
|
||||
@ -93,27 +155,38 @@
|
||||
"loadedSource"
|
||||
"loadedSources"
|
||||
"locale"
|
||||
"locals"
|
||||
"location"
|
||||
"logMessage"
|
||||
"memory"
|
||||
"memoryReference"
|
||||
"message"
|
||||
"method"
|
||||
"mimeType"
|
||||
"module"
|
||||
"moduleCount"
|
||||
"moduleId"
|
||||
"modules"
|
||||
"mostDerivedClass"
|
||||
"name"
|
||||
"named"
|
||||
"namedVariables"
|
||||
"names"
|
||||
"negate"
|
||||
"never"
|
||||
"new"
|
||||
"next"
|
||||
"noDebug"
|
||||
"normal"
|
||||
"notStopped"
|
||||
"number"
|
||||
"offset"
|
||||
"origin"
|
||||
"output"
|
||||
"parameterNames"
|
||||
"parameters"
|
||||
"parameterTypes"
|
||||
"parameterValues"
|
||||
"parameters"
|
||||
"path"
|
||||
"pathFormat"
|
||||
"pause"
|
||||
@ -121,17 +194,32 @@
|
||||
"pointerSize"
|
||||
"presentationHint"
|
||||
"preserveFocusHint"
|
||||
"private"
|
||||
"process"
|
||||
"processId"
|
||||
"progressEnd"
|
||||
"progressId"
|
||||
"progressStart"
|
||||
"progressUpdate"
|
||||
"property"
|
||||
"protected"
|
||||
"public"
|
||||
"read"
|
||||
"readMemory"
|
||||
"readWrite"
|
||||
"reason"
|
||||
"reference"
|
||||
"registers"
|
||||
"removed"
|
||||
"repl"
|
||||
"request"
|
||||
"requestId"
|
||||
"request_seq"
|
||||
"resolveSymbols"
|
||||
"response"
|
||||
"restart"
|
||||
"restartFrame"
|
||||
"result"
|
||||
"reverseContinue"
|
||||
"runInTerminal"
|
||||
"scopes"
|
||||
@ -144,41 +232,66 @@
|
||||
"setExceptionBreakpoints"
|
||||
"setExpression"
|
||||
"setFunctionBreakpoints"
|
||||
"setInstructionBreakpoints"
|
||||
"setVariable"
|
||||
"shellProcessId"
|
||||
"showUser"
|
||||
"singleThread"
|
||||
"snippet"
|
||||
"sortText"
|
||||
"source"
|
||||
"sourceModified"
|
||||
"sourceReference"
|
||||
"sources"
|
||||
"stackFrameId"
|
||||
"stackFrames"
|
||||
"stackTrace"
|
||||
"stacks"
|
||||
"start"
|
||||
"startCollapsed"
|
||||
"startDebugging"
|
||||
"startFrame"
|
||||
"startMethod"
|
||||
"startModule"
|
||||
"started"
|
||||
"statement"
|
||||
"stderr"
|
||||
"stdout"
|
||||
"step"
|
||||
"stepBack"
|
||||
"stepIn"
|
||||
"stepInTargets"
|
||||
"stepOut"
|
||||
"stopped"
|
||||
"string"
|
||||
"subtle"
|
||||
"success"
|
||||
"supportSuspendDebuggee"
|
||||
"supportTerminateDebuggee"
|
||||
"supportedChecksumAlgorithms"
|
||||
"supportsArgsCanBeInterpretedByShell"
|
||||
"supportsBreakpointLocationsRequest"
|
||||
"supportsCancelRequest"
|
||||
"supportsClipboardContext"
|
||||
"supportsCompletionsRequest"
|
||||
"supportsCondition"
|
||||
"supportsConditionalBreakpoints"
|
||||
"supportsConfigurationDoneRequest"
|
||||
"supportsDataBreakpoints"
|
||||
"supportsDelayedStackTraceLoading"
|
||||
"supportsDisassembleRequest"
|
||||
"supportsEvaluateForHovers"
|
||||
"supportsExceptionFilterOptions"
|
||||
"supportsExceptionInfoRequest"
|
||||
"supportsExceptionOptions"
|
||||
"supportsFunctionBreakpoints"
|
||||
"supportsGotoTargetsRequest"
|
||||
"supportsHitConditionalBreakpoints"
|
||||
"supportsInstructionBreakpoints"
|
||||
"supportsInvalidatedEvent"
|
||||
"supportsLoadedSourcesRequest"
|
||||
"supportsLogPoints"
|
||||
"supportsMemoryEvent"
|
||||
"supportsMemoryReferences"
|
||||
"supportsModulesRequest"
|
||||
"supportsProgressReporting"
|
||||
@ -188,38 +301,57 @@
|
||||
"supportsRunInTerminalRequest"
|
||||
"supportsSetExpression"
|
||||
"supportsSetVariable"
|
||||
"supportsSingleThreadExecutionRequests"
|
||||
"supportsStartDebuggingRequest"
|
||||
"supportsStepBack"
|
||||
"supportsStepInTargetsRequest"
|
||||
"supportsSteppingGranularity"
|
||||
"supportsTerminateRequest"
|
||||
"supportsTerminateThreadsRequest"
|
||||
"supportsValueFormattingOptions"
|
||||
"supportsVariablePaging"
|
||||
"supportsVariableType"
|
||||
"supportTerminateDebuggee"
|
||||
"supportsWriteMemoryRequest"
|
||||
"suspendDebuggee"
|
||||
"symbol"
|
||||
"symbolFilePath"
|
||||
"symbolStatus"
|
||||
"systemProcessId"
|
||||
"targetId"
|
||||
"targets"
|
||||
"telemetry"
|
||||
"terminate"
|
||||
"terminated"
|
||||
"terminateDebuggee"
|
||||
"terminateThreads"
|
||||
"terminated"
|
||||
"text"
|
||||
"thread"
|
||||
"threadId"
|
||||
"threadIds"
|
||||
"threads"
|
||||
"timestamp"
|
||||
"title"
|
||||
"title"
|
||||
"totalFrames"
|
||||
"totalModules"
|
||||
"type"
|
||||
"typeName"
|
||||
"unhandled"
|
||||
"unit"
|
||||
"unixTimestampUTC"
|
||||
"unreadableBytes"
|
||||
"uri"
|
||||
"url"
|
||||
"urlLabel"
|
||||
"userUnhandled"
|
||||
"value"
|
||||
"variable"
|
||||
"variables"
|
||||
"variablesReference"
|
||||
"verified"
|
||||
"version"
|
||||
"virtual"
|
||||
"visibility"
|
||||
"watch"
|
||||
"width"
|
||||
"write"
|
||||
"writeMemory"
|
@ -22,6 +22,8 @@
|
||||
#include "dap/protocol.h"
|
||||
#include "dap/session.h"
|
||||
|
||||
#include "fuzz.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
@ -52,53 +54,6 @@ class Event {
|
||||
|
||||
} // namespace
|
||||
|
||||
// List of requests that we handle for fuzzing.
|
||||
#define DAP_REQUEST_LIST() \
|
||||
DAP_REQUEST(dap::AttachRequest, dap::AttachResponse) \
|
||||
DAP_REQUEST(dap::BreakpointLocationsRequest, \
|
||||
dap::BreakpointLocationsResponse) \
|
||||
DAP_REQUEST(dap::CancelRequest, dap::CancelResponse) \
|
||||
DAP_REQUEST(dap::CompletionsRequest, dap::CompletionsResponse) \
|
||||
DAP_REQUEST(dap::ConfigurationDoneRequest, dap::ConfigurationDoneResponse) \
|
||||
DAP_REQUEST(dap::ContinueRequest, dap::ContinueResponse) \
|
||||
DAP_REQUEST(dap::DataBreakpointInfoRequest, dap::DataBreakpointInfoResponse) \
|
||||
DAP_REQUEST(dap::DisassembleRequest, dap::DisassembleResponse) \
|
||||
DAP_REQUEST(dap::DisconnectRequest, dap::DisconnectResponse) \
|
||||
DAP_REQUEST(dap::EvaluateRequest, dap::EvaluateResponse) \
|
||||
DAP_REQUEST(dap::ExceptionInfoRequest, dap::ExceptionInfoResponse) \
|
||||
DAP_REQUEST(dap::GotoRequest, dap::GotoResponse) \
|
||||
DAP_REQUEST(dap::GotoTargetsRequest, dap::GotoTargetsResponse) \
|
||||
DAP_REQUEST(dap::InitializeRequest, dap::InitializeResponse) \
|
||||
DAP_REQUEST(dap::LaunchRequest, dap::LaunchResponse) \
|
||||
DAP_REQUEST(dap::LoadedSourcesRequest, dap::LoadedSourcesResponse) \
|
||||
DAP_REQUEST(dap::ModulesRequest, dap::ModulesResponse) \
|
||||
DAP_REQUEST(dap::NextRequest, dap::NextResponse) \
|
||||
DAP_REQUEST(dap::PauseRequest, dap::PauseResponse) \
|
||||
DAP_REQUEST(dap::ReadMemoryRequest, dap::ReadMemoryResponse) \
|
||||
DAP_REQUEST(dap::RestartFrameRequest, dap::RestartFrameResponse) \
|
||||
DAP_REQUEST(dap::RestartRequest, dap::RestartResponse) \
|
||||
DAP_REQUEST(dap::ReverseContinueRequest, dap::ReverseContinueResponse) \
|
||||
DAP_REQUEST(dap::RunInTerminalRequest, dap::RunInTerminalResponse) \
|
||||
DAP_REQUEST(dap::ScopesRequest, dap::ScopesResponse) \
|
||||
DAP_REQUEST(dap::SetBreakpointsRequest, dap::SetBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetDataBreakpointsRequest, dap::SetDataBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetExceptionBreakpointsRequest, \
|
||||
dap::SetExceptionBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetExpressionRequest, dap::SetExpressionResponse) \
|
||||
DAP_REQUEST(dap::SetFunctionBreakpointsRequest, \
|
||||
dap::SetFunctionBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetVariableRequest, dap::SetVariableResponse) \
|
||||
DAP_REQUEST(dap::SourceRequest, dap::SourceResponse) \
|
||||
DAP_REQUEST(dap::StackTraceRequest, dap::StackTraceResponse) \
|
||||
DAP_REQUEST(dap::StepBackRequest, dap::StepBackResponse) \
|
||||
DAP_REQUEST(dap::StepInRequest, dap::StepInResponse) \
|
||||
DAP_REQUEST(dap::StepInTargetsRequest, dap::StepInTargetsResponse) \
|
||||
DAP_REQUEST(dap::StepOutRequest, dap::StepOutResponse) \
|
||||
DAP_REQUEST(dap::TerminateRequest, dap::TerminateResponse) \
|
||||
DAP_REQUEST(dap::TerminateThreadsRequest, dap::TerminateThreadsResponse) \
|
||||
DAP_REQUEST(dap::ThreadsRequest, dap::ThreadsResponse) \
|
||||
DAP_REQUEST(dap::VariablesRequest, dap::VariablesResponse)
|
||||
|
||||
// Fuzzing main function.
|
||||
// See http://llvm.org/docs/LibFuzzer.html for details.
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
75
fuzz/fuzz.h
Normal file
75
fuzz/fuzz.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://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.
|
||||
|
||||
// Generated with protocol_gen.go -- do not edit this file.
|
||||
// go run scripts/protocol_gen/protocol_gen.go
|
||||
//
|
||||
// DAP version 1.59.0
|
||||
|
||||
#ifndef dap_fuzzer_h
|
||||
#define dap_fuzzer_h
|
||||
|
||||
#include "dap/protocol.h"
|
||||
|
||||
#define DAP_REQUEST_LIST() \
|
||||
DAP_REQUEST(dap::AttachRequest, dap::AttachResponse) \
|
||||
DAP_REQUEST(dap::BreakpointLocationsRequest, \
|
||||
dap::BreakpointLocationsResponse) \
|
||||
DAP_REQUEST(dap::CancelRequest, dap::CancelResponse) \
|
||||
DAP_REQUEST(dap::CompletionsRequest, dap::CompletionsResponse) \
|
||||
DAP_REQUEST(dap::ConfigurationDoneRequest, dap::ConfigurationDoneResponse) \
|
||||
DAP_REQUEST(dap::ContinueRequest, dap::ContinueResponse) \
|
||||
DAP_REQUEST(dap::DataBreakpointInfoRequest, dap::DataBreakpointInfoResponse) \
|
||||
DAP_REQUEST(dap::DisassembleRequest, dap::DisassembleResponse) \
|
||||
DAP_REQUEST(dap::DisconnectRequest, dap::DisconnectResponse) \
|
||||
DAP_REQUEST(dap::EvaluateRequest, dap::EvaluateResponse) \
|
||||
DAP_REQUEST(dap::ExceptionInfoRequest, dap::ExceptionInfoResponse) \
|
||||
DAP_REQUEST(dap::GotoRequest, dap::GotoResponse) \
|
||||
DAP_REQUEST(dap::GotoTargetsRequest, dap::GotoTargetsResponse) \
|
||||
DAP_REQUEST(dap::InitializeRequest, dap::InitializeResponse) \
|
||||
DAP_REQUEST(dap::LaunchRequest, dap::LaunchResponse) \
|
||||
DAP_REQUEST(dap::LoadedSourcesRequest, dap::LoadedSourcesResponse) \
|
||||
DAP_REQUEST(dap::ModulesRequest, dap::ModulesResponse) \
|
||||
DAP_REQUEST(dap::NextRequest, dap::NextResponse) \
|
||||
DAP_REQUEST(dap::PauseRequest, dap::PauseResponse) \
|
||||
DAP_REQUEST(dap::ReadMemoryRequest, dap::ReadMemoryResponse) \
|
||||
DAP_REQUEST(dap::RestartFrameRequest, dap::RestartFrameResponse) \
|
||||
DAP_REQUEST(dap::RestartRequest, dap::RestartResponse) \
|
||||
DAP_REQUEST(dap::ReverseContinueRequest, dap::ReverseContinueResponse) \
|
||||
DAP_REQUEST(dap::RunInTerminalRequest, dap::RunInTerminalResponse) \
|
||||
DAP_REQUEST(dap::ScopesRequest, dap::ScopesResponse) \
|
||||
DAP_REQUEST(dap::SetBreakpointsRequest, dap::SetBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetDataBreakpointsRequest, dap::SetDataBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetExceptionBreakpointsRequest, \
|
||||
dap::SetExceptionBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetExpressionRequest, dap::SetExpressionResponse) \
|
||||
DAP_REQUEST(dap::SetFunctionBreakpointsRequest, \
|
||||
dap::SetFunctionBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetInstructionBreakpointsRequest, \
|
||||
dap::SetInstructionBreakpointsResponse) \
|
||||
DAP_REQUEST(dap::SetVariableRequest, dap::SetVariableResponse) \
|
||||
DAP_REQUEST(dap::SourceRequest, dap::SourceResponse) \
|
||||
DAP_REQUEST(dap::StackTraceRequest, dap::StackTraceResponse) \
|
||||
DAP_REQUEST(dap::StartDebuggingRequest, dap::StartDebuggingResponse) \
|
||||
DAP_REQUEST(dap::StepBackRequest, dap::StepBackResponse) \
|
||||
DAP_REQUEST(dap::StepInRequest, dap::StepInResponse) \
|
||||
DAP_REQUEST(dap::StepInTargetsRequest, dap::StepInTargetsResponse) \
|
||||
DAP_REQUEST(dap::StepOutRequest, dap::StepOutResponse) \
|
||||
DAP_REQUEST(dap::TerminateRequest, dap::TerminateResponse) \
|
||||
DAP_REQUEST(dap::TerminateThreadsRequest, dap::TerminateThreadsResponse) \
|
||||
DAP_REQUEST(dap::ThreadsRequest, dap::ThreadsResponse) \
|
||||
DAP_REQUEST(dap::VariablesRequest, dap::VariablesResponse) \
|
||||
DAP_REQUEST(dap::WriteMemoryRequest, dap::WriteMemoryResponse)
|
||||
|
||||
#endif // dap_fuzzer_h
|
@ -93,6 +93,19 @@ namespace dap {
|
||||
`
|
||||
|
||||
cppEpilogue = `} // namespace dap
|
||||
`
|
||||
fuzzerHeaderPrologue = commonPrologue + `
|
||||
#ifndef dap_fuzzer_h
|
||||
#define dap_fuzzer_h
|
||||
|
||||
#include "dap/protocol.h"
|
||||
|
||||
#define DAP_REQUEST_LIST() \
|
||||
`
|
||||
|
||||
fuzzerHeaderEpilogue = `
|
||||
|
||||
#endif // dap_fuzzer_h
|
||||
`
|
||||
)
|
||||
|
||||
@ -187,6 +200,7 @@ type cppField struct {
|
||||
ty cppType
|
||||
name string
|
||||
optional bool
|
||||
enumVals []string
|
||||
}
|
||||
|
||||
// cppType is an interface for all C++ generated types
|
||||
@ -207,6 +221,10 @@ type cppType interface {
|
||||
WriteHeader(w io.Writer)
|
||||
// WriteHeader() writes the type definition to the given .cpp file writer
|
||||
WriteCPP(w io.Writer)
|
||||
// WriteFuzzerH() writes the fuzzer DAP_REQUEST() macro to the given .h writer
|
||||
WriteFuzzerH(w io.Writer)
|
||||
// GetFuzzerNames() returns a list of the protocol name, the fields, and field enum values for this type
|
||||
GetFuzzerNames() []string
|
||||
}
|
||||
|
||||
// cppStruct implements the cppType interface, describing a C++ structure
|
||||
@ -295,11 +313,54 @@ func (s *cppStruct) WriteCPP(w io.Writer) {
|
||||
io.WriteString(w, ");\n\n")
|
||||
}
|
||||
|
||||
func (s *cppStruct) WriteFuzzerH(header io.Writer) {
|
||||
// only write fuzzer macros for Request types
|
||||
if s.base != "Request" {
|
||||
return
|
||||
}
|
||||
|
||||
io.WriteString(header, "DAP_REQUEST(dap::")
|
||||
io.WriteString(header, s.name)
|
||||
io.WriteString(header, ", dap::")
|
||||
|
||||
responseType := ""
|
||||
|
||||
// check typedefs for response
|
||||
for _, t := range s.typedefs {
|
||||
if t.from == "Response" {
|
||||
responseType = t.to.Name()
|
||||
}
|
||||
}
|
||||
|
||||
// if no response, throw an error
|
||||
if responseType == "" {
|
||||
panic("No corresponding response type found for " + s.name)
|
||||
}
|
||||
|
||||
io.WriteString(header, responseType)
|
||||
io.WriteString(header, ") \\\n")
|
||||
}
|
||||
|
||||
func (s *cppStruct) GetFuzzerNames() []string {
|
||||
ret := []string{}
|
||||
if s.protoname != "" {
|
||||
ret = append(ret, s.protoname)
|
||||
}
|
||||
for _, f := range s.fields {
|
||||
ret = append(ret, f.name)
|
||||
if (f.enumVals != nil) && (len(f.enumVals) > 0) {
|
||||
ret = append(ret, f.enumVals...)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// cppStruct implements the cppType interface, describing a C++ typedef
|
||||
type cppTypedef struct {
|
||||
from string // Name of the typedef
|
||||
to cppType // Target of the typedef
|
||||
desc string // Description
|
||||
from string // Name of the typedef
|
||||
to cppType // Target of the typedef
|
||||
desc string // Description
|
||||
enumVals []string // Enum values
|
||||
}
|
||||
|
||||
func (ty *cppTypedef) Name() string { return ty.from }
|
||||
@ -320,7 +381,11 @@ func (ty *cppTypedef) WriteHeader(w io.Writer) {
|
||||
io.WriteString(w, ty.to.Name())
|
||||
io.WriteString(w, ";\n\n")
|
||||
}
|
||||
func (ty *cppTypedef) WriteCPP(w io.Writer) {}
|
||||
func (ty *cppTypedef) WriteCPP(w io.Writer) {}
|
||||
func (ty *cppTypedef) WriteFuzzerH(w io.Writer) {}
|
||||
func (s *cppTypedef) GetFuzzerNames() []string {
|
||||
return s.enumVals
|
||||
}
|
||||
|
||||
// cppStruct implements the cppType interface, describing a basic C++ type
|
||||
type cppBasicType struct {
|
||||
@ -330,13 +395,44 @@ type cppBasicType struct {
|
||||
defaultValue string // Default value for fields of this type
|
||||
}
|
||||
|
||||
func (ty *cppBasicType) Name() string { return ty.name }
|
||||
func (ty *cppBasicType) Dependencies() []cppType { return ty.deps }
|
||||
func (ty *cppBasicType) File() cppTargetFile { return types }
|
||||
func (ty *cppBasicType) Description() string { return ty.desc }
|
||||
func (ty *cppBasicType) DefaultValue() string { return ty.defaultValue }
|
||||
func (ty *cppBasicType) WriteHeader(w io.Writer) {}
|
||||
func (ty *cppBasicType) WriteCPP(w io.Writer) {}
|
||||
func (ty *cppBasicType) Name() string { return ty.name }
|
||||
func (ty *cppBasicType) Dependencies() []cppType { return ty.deps }
|
||||
func (ty *cppBasicType) File() cppTargetFile { return types }
|
||||
func (ty *cppBasicType) Description() string { return ty.desc }
|
||||
func (ty *cppBasicType) DefaultValue() string { return ty.defaultValue }
|
||||
func (ty *cppBasicType) WriteHeader(w io.Writer) {}
|
||||
func (ty *cppBasicType) WriteCPP(w io.Writer) {}
|
||||
func (ty *cppBasicType) WriteFuzzerH(w io.Writer) {}
|
||||
func (ty *cppBasicType) GetFuzzerNames() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func stringify(s string) string {
|
||||
return "\"" + s + "\""
|
||||
}
|
||||
|
||||
func stringifyArray(s []string) []string {
|
||||
ret := []string{}
|
||||
if s == nil {
|
||||
return ret
|
||||
}
|
||||
for _, v := range s {
|
||||
ret = append(ret, stringify(v))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func removeDuplicateStr(strSlice []string) []string {
|
||||
allKeys := make(map[string]bool)
|
||||
list := []string{}
|
||||
for _, item := range strSlice {
|
||||
if _, value := allKeys[item]; !value {
|
||||
allKeys[item] = true
|
||||
list = append(list, item)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// sanitize() returns the given identifier transformed into a legal C++ identifier
|
||||
func sanitize(s string) string {
|
||||
@ -455,11 +551,19 @@ func (r *root) buildRootStruct(ty *cppStruct, def *definition) error {
|
||||
|
||||
optional := !required[propName]
|
||||
desc := appendEnumDetails(property.Description, property.OpenEnum, property.ClosedEnum)
|
||||
enumVals := []string{}
|
||||
if len(property.ClosedEnum) > 0 {
|
||||
enumVals = append(enumVals, property.ClosedEnum...)
|
||||
}
|
||||
if len(property.OpenEnum) > 0 {
|
||||
enumVals = append(enumVals, property.OpenEnum...)
|
||||
}
|
||||
ty.fields = append(ty.fields, cppField{
|
||||
desc: desc,
|
||||
ty: propTy,
|
||||
name: propName,
|
||||
optional: optional,
|
||||
enumVals: enumVals,
|
||||
})
|
||||
|
||||
ty.deps = append(ty.deps, propTy)
|
||||
@ -632,6 +736,16 @@ func (r *root) buildTypes() ([]cppType, error) {
|
||||
from: entry.name,
|
||||
to: enumTy,
|
||||
desc: enumTy.Description(),
|
||||
enumVals: func() []string {
|
||||
ret := []string{}
|
||||
if len(entry.def.ClosedEnum) > 0 {
|
||||
ret = entry.def.ClosedEnum
|
||||
}
|
||||
if len(entry.def.OpenEnum) > 0 {
|
||||
ret = append(ret, entry.def.OpenEnum...)
|
||||
}
|
||||
return ret
|
||||
}(),
|
||||
}
|
||||
entry.def.cppType = ty
|
||||
out = append(out, entry.def.cppType)
|
||||
@ -680,8 +794,8 @@ func run() error {
|
||||
return fmt.Errorf("Failed to load JSON file from '%v': %w", protocolURL, err)
|
||||
}
|
||||
|
||||
hPath, cppPaths, cMakeListsPath := outputPaths()
|
||||
if err := emitFiles(&protocol, hPath, cppPaths, pkg.Version); err != nil {
|
||||
hPath, cppPaths, cMakeListsPath, fuzzerhPath, fuzzerDictPath := outputPaths()
|
||||
if err := emitFiles(&protocol, hPath, cppPaths, fuzzerhPath, fuzzerDictPath, pkg.Version); err != nil {
|
||||
return fmt.Errorf("Failed to emit files: %w", err)
|
||||
}
|
||||
|
||||
@ -698,6 +812,9 @@ func run() error {
|
||||
return fmt.Errorf("Failed to run clang-format on '%v':\n%v\n%w", p, string(out), err)
|
||||
}
|
||||
}
|
||||
if out, err := exec.Command(clangfmt, "-i", fuzzerhPath).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("Failed to run clang-format on '%v':\n%v\n%w", fuzzerhPath, string(out), err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("clang-format not found on PATH. Please format before committing.")
|
||||
}
|
||||
@ -725,7 +842,7 @@ func updateCMakePackageVersion(cMakeListsPath string, version string) error {
|
||||
// emitFiles() opens each of the C++ files, generates the cppType definitions
|
||||
// from the schema root, then writes the types to the C++ files in dependency
|
||||
// order.
|
||||
func emitFiles(r *root, hPath string, cppPaths map[cppTargetFile]string, version string) error {
|
||||
func emitFiles(r *root, hPath string, cppPaths map[cppTargetFile]string, fuzzerhPath string, fuzzerDictPath string, version string) error {
|
||||
h, err := os.Create(hPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -741,10 +858,19 @@ func emitFiles(r *root, hPath string, cppPaths map[cppTargetFile]string, version
|
||||
defer f.Close()
|
||||
}
|
||||
|
||||
fuzzer_h, err := os.Create(fuzzerhPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fuzzerDict, err := os.Create(fuzzerDictPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.WriteString(strings.ReplaceAll(headerPrologue, versionTag, version))
|
||||
for _, f := range cppFiles {
|
||||
f.WriteString(strings.ReplaceAll(cppPrologue, versionTag, version))
|
||||
}
|
||||
fuzzer_h.WriteString(strings.ReplaceAll(fuzzerHeaderPrologue, versionTag, version))
|
||||
|
||||
types, err := r.buildTypes()
|
||||
if err != nil {
|
||||
@ -757,6 +883,17 @@ func emitFiles(r *root, hPath string, cppPaths map[cppTargetFile]string, version
|
||||
}
|
||||
|
||||
seen := map[string]bool{}
|
||||
// Prepopulate the names list with the types that are not generated from the schema.
|
||||
ProtocolMessageFuzzerNames := []string{"seq", "type", "request", "response", "event"}
|
||||
RequestMessageFuzzerNames := []string{"request", "type", "command", "arguments"}
|
||||
EventMessageFuzzerNames := []string{"event", "type", "event", "body"}
|
||||
ResponseMessageFuzzerNames := []string{"response", "type", "request_seq", "success", "command", "message", "body",
|
||||
"cancelled", "notStopped"}
|
||||
fuzzerNames := []string{}
|
||||
fuzzerNames = append(fuzzerNames, ProtocolMessageFuzzerNames...)
|
||||
fuzzerNames = append(fuzzerNames, RequestMessageFuzzerNames...)
|
||||
fuzzerNames = append(fuzzerNames, EventMessageFuzzerNames...)
|
||||
fuzzerNames = append(fuzzerNames, ResponseMessageFuzzerNames...)
|
||||
var emit func(cppType) error
|
||||
emit = func(ty cppType) error {
|
||||
name := ty.Name()
|
||||
@ -771,6 +908,11 @@ func emitFiles(r *root, hPath string, cppPaths map[cppTargetFile]string, version
|
||||
}
|
||||
ty.WriteHeader(h)
|
||||
ty.WriteCPP(cppFiles[ty.File()])
|
||||
ty.WriteFuzzerH(fuzzer_h)
|
||||
|
||||
// collect protoname, field names, and field enum values for dictionary
|
||||
fuzzerNames = append(fuzzerNames, ty.GetFuzzerNames()...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -785,10 +927,22 @@ func emitFiles(r *root, hPath string, cppPaths map[cppTargetFile]string, version
|
||||
}
|
||||
}
|
||||
|
||||
// sort names alphabetically
|
||||
sort.Strings(fuzzerNames)
|
||||
// remove duplicates
|
||||
fuzzerNames = removeDuplicateStr(fuzzerNames)
|
||||
// append "" to each name
|
||||
fuzzerNames = stringifyArray(fuzzerNames)
|
||||
dict := strings.Join(fuzzerNames, "\n")
|
||||
if _, err := io.WriteString(fuzzerDict, dict); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.WriteString(headerEpilogue)
|
||||
for _, f := range cppFiles {
|
||||
f.WriteString(cppEpilogue)
|
||||
}
|
||||
fuzzer_h.WriteString(fuzzerHeaderEpilogue)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -811,7 +965,7 @@ func loadJSONFile(url string, obj interface{}) error {
|
||||
}
|
||||
|
||||
// outputPaths() returns a path to the target C++ .h file and .cpp files, and the CMakeLists.txt
|
||||
func outputPaths() (string, cppTargetFilePaths, string) {
|
||||
func outputPaths() (string, cppTargetFilePaths, string, string, string) {
|
||||
_, thisFile, _, _ := runtime.Caller(1)
|
||||
thisDir := path.Dir(thisFile)
|
||||
h := path.Join(thisDir, "../../include/dap/protocol.h")
|
||||
@ -822,5 +976,7 @@ func outputPaths() (string, cppTargetFilePaths, string) {
|
||||
types: path.Join(thisDir, "../../src/protocol_types.cpp"),
|
||||
}
|
||||
CMakeLists := path.Join(thisDir, "../../CMakeLists.txt")
|
||||
return h, cpp, CMakeLists
|
||||
fuzzer_h := path.Join(thisDir, "../../fuzz/fuzz.h")
|
||||
fuzzer_dict := path.Join(thisDir, "../../fuzz/dictionary.txt")
|
||||
return h, cpp, CMakeLists, fuzzer_h, fuzzer_dict
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user