// +build gofuzz /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package fuzz import ( "context" "fmt" "strconv" "shared" "tutorial" "github.com/apache/thrift/lib/go/thrift" ) const nbFuzzedProtocols = 2 func fuzzChooseProtocol(d byte, t thrift.TTransport) thrift.TProtocol { switch d % nbFuzzedProtocols { default: fallthrough case 0: return thrift.NewTBinaryProtocolFactoryConf(nil).GetProtocol(t) case 1: return thrift.NewTCompactProtocolFactoryConf(nil).GetProtocol(t) } } func Fuzz(data []byte) int { if len(data) < 2 { return 0 } inputTransport := thrift.NewTMemoryBuffer() inputTransport.Buffer.Write(data[2:]) outputTransport := thrift.NewTMemoryBuffer() outputProtocol := fuzzChooseProtocol(data[0], outputTransport) inputProtocol := fuzzChooseProtocol(data[1], inputTransport) ctx := thrift.SetResponseHelper( context.Background(), thrift.TResponseHelper{ THeaderResponseHelper: thrift.NewTHeaderResponseHelper(outputProtocol), }, ) handler := NewCalculatorHandler() processor := tutorial.NewCalculatorProcessor(handler) ok := true var err error for ok { ok, err = processor.Process(ctx, inputProtocol, outputProtocol) if err != nil { // Handle parse error return 0 } res := make([]byte, 1024) n, err := outputTransport.Buffer.Read(res) fmt.Printf("lol %d %s %v\n", n, err, res) } return 1 } type CalculatorHandler struct { log map[int]*shared.SharedStruct } func NewCalculatorHandler() *CalculatorHandler { return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)} } func (p *CalculatorHandler) Ping(ctx context.Context) (err error) { fmt.Print("ping()\n") return nil } func (p *CalculatorHandler) Add(ctx context.Context, num1 int32, num2 int32) (retval17 int32, err error) { fmt.Print("add(", num1, ",", num2, ")\n") return num1 + num2, nil } func (p *CalculatorHandler) Calculate(ctx context.Context, logid int32, w *tutorial.Work) (val int32, err error) { fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") switch w.Op { case tutorial.Operation_ADD: val = w.Num1 + w.Num2 break case tutorial.Operation_SUBTRACT: val = w.Num1 - w.Num2 break case tutorial.Operation_MULTIPLY: val = w.Num1 * w.Num2 break case tutorial.Operation_DIVIDE: if w.Num2 == 0 { ouch := tutorial.NewInvalidOperation() ouch.WhatOp = int32(w.Op) ouch.Why = "Cannot divide by 0" err = ouch return } val = w.Num1 / w.Num2 break default: ouch := tutorial.NewInvalidOperation() ouch.WhatOp = int32(w.Op) ouch.Why = "Unknown operation" err = ouch return } entry := shared.NewSharedStruct() entry.Key = logid entry.Value = strconv.Itoa(int(val)) k := int(logid) p.log[k] = entry return val, err } func (p *CalculatorHandler) GetStruct(ctx context.Context, key int32) (*shared.SharedStruct, error) { fmt.Print("getStruct(", key, ")\n") v, _ := p.log[int(key)] return v, nil } func (p *CalculatorHandler) Zip(ctx context.Context) (err error) { fmt.Print("zip()\n") return nil }