autogenerate fuzzing data from spec (#95)

This commit is contained in:
nikitalita 2023-03-13 10:17:41 -07:00 committed by GitHub
parent 59819690ec
commit bf1f56547c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 390 additions and 72 deletions

View File

@ -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"

View File

@ -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
View 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

View File

@ -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
}