栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【Custom Mutator Fuzz】Protocol Buffer基础(下):C++生成代码介绍 + 配套代码

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Custom Mutator Fuzz】Protocol Buffer基础(下):C++生成代码介绍 + 配套代码

前言

在上一篇【Custom Mutator Fuzz】Protocol Buffer基础(上):proto2编写格式文章中,主要讲解了protobuf生成各语言调用文件的方法,以及.proto文件的编写格式,这篇文章主讲的是生成的C++文件如何进行调用。因为毕竟最后和fuzzer一起使用的还是生成的C++调用接口。因为上一篇文章讲解的是proto2的语法,所以本篇依然还是proto2生成代码讲解

本文原文链接:https://hollk.blog.csdn.net/article/details/124558304

模糊测试系列往期回顾:
【Custom Mutator Fuzz】Protocol Buffer基础(上):proto2编写格式
【Custom Mutator Fuzz】libprotobuf-mutator安装
LibFuzzer学习(三):使用小trick
LibFuzzer学习(二):提高代码覆盖率和速度
LibFuzzer学习(一):轻松找到心脏出血漏洞
Fuzz出结果不会看?Address Sanitizer(ASan)各类溢出demo分析
Fuzzing101 Exercise 5 - LibXML2 学习笔记
Fuzzing101 Exercise 4 - LibTIFF 学习笔记
Fuzzing101 Exercise 3 - TCPdump 学习笔记
Fuzzing101 Exercise 2 - Libexif 学习笔记
Fuzzing101 Exercise 1 - Xpdf学习笔记
AFL源码分析之afl-fuzz.c详细注释(二):FUZZ执行流程(五万字警告,慎入)
AFL源码分析之afl-fuzz.c详细注释(一):初始配置(6万字警告,慎入)
AFL源码分析之afl-gcc.c详细注释
AFL源码分析之afl-as.c详细注释
免费资源:AFL-2.57b.zip(AFL源码分析章节版本)

protobuf文章中所用到的代码,均可在https://download.csdn.net/download/qq_41202237/85331019这里下载到,当然为了友好,文章内部也有源码,只不过需要自己编译一下。这个压缩包里都是按照归类编译好的,如果你觉得自己编译比较麻烦,也可以请我喝杯咖啡~

Package

在.proto中声明package名称之后,protc就会将所有制定内容放置在对应的C++命名空间中,这里举一个例子:

// Filename:hollk.proto
// Path:1_package/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollk.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

生成的代码部分展示(hollk.pb.h):


已经一看到生成的C++命名空间为HollkProtoTest

Message 一般类型

在.proto文件中定义一个messgae后,编译器会生成对应message名称的类,下面做一个例子:

// Filename:hollk.proto
// Path:2_message/common/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollk.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{}

下面是编译后的hollk.pb.h部分代码截图

上图中用红色方框圈出来的就是HollkMessage类提供的public方法,每个message都会生成这部分的代码,下面逐一讲解一下:

  • HollkMessage():默认构造函数
  • ~HollkMessage():默认析构函数
  • HollkMessage(const HollkMessage& from):复制构造函数
  • HollkMessage(HollkMessage&& from):移动构造函数
  • HollkMessage& operator=(const HollkMessage& from):赋值运算符重载函数
  • HollkMessage& operator=(HollkMessage&& from) :移动赋值运算符重载函数
  • const UnknownFieldSet& unknown_fields():返回在解析message过程中遇到的未知字段
  • UnknownFieldSet* mutable_unknown_fields():返回在解析message过程中遇到的未知字段所在地址
  • Swap(HollkMessage* other):message内容交换函数
嵌套类型

前面一篇文章中介绍过,message中可以进行嵌套使用,所以举下面这个例子介绍一下嵌套时生成代码:

// Filename:hollknest.proto
// Path:2_message/nest/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    message HollkNest{}
}

下面是编译后的hollknest.pb.h部分代码截图


可以看到在message嵌套类型中,编译器会生成两个类:HollkMessage和HollkMessage_HollkNest。这两个类中的公共方法和一般类型中的无异。同时在后面的代码中还可以找到:

这说明可以使用嵌套类型的类:HollkMessage::HollkNest

字段

protoc编译器会为.proto文件中的每一个字段生成一组访问方法。并且编译器会按照每个字段编号生成一个或多个整数常量,常量名称格式为k + 字段名称 + FieldNumber,例如:

optional int32 hollkfuzz = 1;
required int32 hollkpwntools = 2;

那么生成的.pb.h中就会出现图片中的整数常量:

在前面讲过三种修饰符:optional、required、repeated。这三个中可以通过操作次数进行分类,optional和required可以看做单次(Singular)操作字段,repeated属于重复多次(Repeated)操作字段。还有比较特殊的就是oneof和map,oneof是一组数据中取一个字段进行操作,map在模糊测试中不常用,这里进行详细说明。protoc编译器通过将Singular、Repeated和Oneof这三类操作与整型(singular)、字符型(string)、枚举(enum)、嵌套(embedded)进行组合生成如下几种访问方法归类

下面就会按照这个分类逐个介绍生成文件中对应的字段方法

单次数值类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/1_singular/1_numeric/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    optional int32 hollkfuzz = 1;
    required int32 hollkpwntools = 2;
}

下面是编译后的hollk.pb.h部分代码截图

可以看到其实protobuf编译器对于singular操作中optional和required修饰的字段,编译的方法是一样的,所以后续singular部分就选optional所在字段的方法进行解读了:

  • bool has_hollkfuzz() const:如果设置了该字段的值,则返回true。如果清除了该字段的值,则返回false
  • int32 hollkfuzz() const:返回当前字段的值,如果没有设置该字段,则返回默认值
  • void set_hollkfuzz(int32 value):设置该字段的值,如果完成该函数的调用,has_hollkfuzz()将返回true,hollkfuzz()函数返回value
  • void clear_hollkfuzz():清除字段的值,如果完成该函数的调用,has_hollkfuzz()函数将返回false,hollkfuzz()函数返回默认值
单次字符串类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/1_singular/2_string/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    optional string hollkfuzz = 1;
    optional bytes hollkafl = 2;
    required string hollkpwntools = 3;
    required bytes hollklibfuzzer = 4;
}

下面是编译后的hollk.pb.h部分代码截图

由于optional与required方法相同,string与bytes方法相同,因此上图中只截取了optional string hollkfuzz = 1字段的部分

  • bool has_hollkfuzz() const:如果设置了该字段的值,则返回true,如果清除了该字段的值,则返回false
  • const string& hollkfuzz() const:返回该字段的当前值,如果该字段没有值,则返回默认值
  • void clear_hollkfuzz():清除该字段内容,has_hollkfuzz()返回false,hollkfuzz()函数返回默认值
  • void set_hollkfuzz(ArgT0&& arg0, ArgT... args):这里用了一个关键字模板
    • 一般情况下,函数参数为const string& value,
    • 如果是C++11及更高版本,函数参数为string&& value,调用该函数将对该字段进行字符串赋值,完成该函数调用后,has_hollkfuzz()函数返回true,hollkfuzz()函数返回value
    • 如果为C语言方式,则函数参数为const char* value,调用该函数对该字段进行以空字符结尾的字符串赋值,完成该函数调用后,has_hollkfuzz()函数返回true,hollkfuzz()函数返回value
  • string* mutable_hollkfuzz():返回指向该字段值的指针,如果该字段中已经设置了值,则has_hollkfuzz()函数返回true,hollkfuzz()函数返回字符串指针。如果该字段中没有值,则返回NULL
  • void set_allocated_hollkfuzz(string* hollkfuzz):为string指针类型对象赋值后并释放。这个函数调用需要特别小心,其中的参数是一个string指针类型的对象,该指针对象必须是新构造的,因为该函数对string指针对象进行赋值后将会释放,如果传入的参数为一个已经析构的对象,那会导致内存错误
  • string* release_hollkfuzz():释放字段内存空间,并返回string对象的指针,调用者将会重新获取对象的所有权
单次枚举类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/1_singular/3_enum/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    enum Option{
        CORPUS = 0;
        FUZZER = 1;
    }
    optional Option hollkfuzz = 1;
    required Option hollklibfuzzer = 2;
}

下面是编译后的hollk.pb.h部分代码截图

其实和前面的单次整型字段也没有什么太大的区别,只不过字段类型变成了枚举的Option:

  • bool has_hollkfuzz() const:如果设置了该字段,则返回true,如果清除了带字段,则返回false
  • HollkMessage_Option hollkfuzz() const:返回当前字段的值,如果该字段没有设置值,则返回默认值
  • void set_hollkfuzz(HollkMessage_Option value):为当前字段设置值,如果完成该函数调用,has_hollkfuzz()函数将返回true,hollkfuzz()函数返回value
  • void clear_hollkfuzz():清除该字段的值,乳沟完成该函数调用,has_hollkfuzz()函数将返回false,hollkfuzz()函数返回默认值
单次message嵌套类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/1_singular/4_embedded/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    message Embedded{}
    optional Embedded hollkfuzz = 1;
    required Embedded hollklibafl = 2;
}

下面是编译后的hollk.pb.h部分代码截图

  • bool has_hollkfuzz() const:如果设置了该字段,则返回true,如果清除了带字段,则返回false
  • const HollkMessage_Embedded& hollkfuzz() const:返回该字段的当前值,如果该字段没有设置值,则返回一个未设置任何字段的Embedded,可能是Embedded::default_instance()
  • HollkMessage_Embedded* mutable_hollkfuzz():返回指向存储字段值的可变Embedded 对象的指针,如果在调用之前未设置该字段,那么返回不设置任何字段的Embedded。调用该函数后has_hollkfuzz()返回true,hollkfuzz()函数返回同一实例Embedded的引用
  • void clear_hollkfuzz():清除字段的值,has_hollkfuzz()将返回false,hollkfuzz()返回默认值
  • void set_allocated_hollkfuzz(HollkMessage_Embedded* hollkfuzz):如果该字段有值,则释放该值并将Embedded对象设置为字段
    • 如果Embedded指针不为NULL:message获得分配Embedded对象的所有权,has_hollkfuzz()返回true
    • 如果Embedded指针为NULL:进行类似clear_hollkfuzz()的操作
  • HollkMessage_Embedded* release_hollkfuzz():释放字段的所有权并返回Embedded对象的指针,调用者重新获得Embedded对象的所有权。has_hollkfuzz() 返回false,hollkfuzz()返回默认值
重复数值类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/2_repeated/1_numeric/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    repeated int32 hollkfuzz = 1;
}

下面是编译后的hollk.pb.h部分代码截图

  • int hollkfuzz_size() const:返回该字段中的元素数量
  • int32 hollkfuzz(int index) const:次不过0开始返回给定index处的元素值,index范围不可以超过[0~hollkfuzz_size()]
  • void set_hollkfuzz(int index, ::PROTOBUF_NAMESPACE_ID::int32 value):从0开始索引,在给定的index索引处设置值value
  • void add_hollkfuzz(::PROTOBUF_NAMESPACE_ID::int32 value):为该字段添加一个新的元素
  • void clear_hollkfuzz():清除字段中所有元素,调用结束后hollkfuzz_size()函数返回0
  • const RepeatedField& hollkfuzz() const:返回存储字段元素的底层的 RepeatedField
  • RepeatedField* mutable_hollkfuzz():返回存储字段元素的底层的 RepeatedField的mutable指针
重复字符串类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/2_repeated/2_string/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    repeated string hollkfuzz = 1;
    repeated bytes hollkafl = 2;
}

下面是编译后的hollk.pb.h部分代码截图

  • int hollkfuzz_size() const:返回该字段中的元素数量
  • string& hollkfuzz(int index) const:从0开始索引,返回给定的index索引处的元素值,index范围不可以超过[0~hollkfuzz_size()]
  • void set_hollkfuzz(int index, const string& value):从0开始索引,在给定的index索引处设置值value
  • void set_hollkfuzz(int index, const char* value):C语言方式,从0开始索引,在给定的index索引处设置以null为结尾的元素值
  • void set_hollkfuzz(int index, const char* value, size_t size):C语言方式,从0开始索引,在给定的index索引处设置size长度的元素值
  • string* mutable_hollkfuzz(int index):从0开始索引,返回给定索引处元素值所在指针
  • string* add_hollkfuzz():在字段末尾添加一个新的空字符串元素,并返回指向该元素的指针
  • void add_hollkfuzz(const string& value):在字段结尾添加一个值为value的新元素
  • void add_hollkfuzz(const char* value):C语言方式,在字段结为添加一个值为value并以null为结尾的新元素
  • void add_hollkfuzz(const char* value, size_t size):C语言方式,在字段结为添加一个值为size长度的value值的新元素
  • void clear_hollkfuzz():清除字段中所有元素,调用结束后hollkfuzz_size()函数返回0
  • RepeatedPtrField& hollkfuzz() const:返回存储字段元素的底层的 RepeatedField
  • RepeatedPtrField* mutable_hollkfuzz():返回存储字段元素的底层的 RepeatedField的mutable指针
重复枚举类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/2_repeated/3_enum/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    enum Option{
        CORPUS = 0;
        FUZZER = 1;
    }
    repeated Option hollkfuzz = 1;
}

下面是编译后的hollk.pb.h部分代码截图

  • int hollkfuzz_size() const:返回该字段中的元素数量
  • HollkMessage_Option hollkfuzz(int index) const:从0开始索引,返回给定index处的元素,index范围不可以超过[0~hollkfuzz_size()]
  • void set_hollkfuzz(int index, HollkMessage_Option value):从0开始索引,在给定的index索引处设置值value
  • void add_hollkfuzz(HollkMessage_Option value):为该字段添加一个新的元素
  • void clear_hollkfuzz():清除字段中所有元素,调用结束后hollkfuzz_size()函数返回0
  • const RepeatedField& hollkfuzz() const:返回存储字段元素的底层的 RepeatedField
  • RepeatedField* mutable_hollkfuzz():返回存储字段元素的底层的 RepeatedField的mutable指针
重复message嵌套类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/2_repeated/4_embedded/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    message Option{}
    repeated Option hollkfuzz = 1;
}

下面是编译后的hollk.pb.h部分代码截图

  • int hollkfuzz_size() const:返回该字段中的元素数量
  • HollkMessage_Embedded& hollkfuzz(int index) const:从0开始返回给定index处的元素值,index范围不可以超过[0~hollkfuzz_size()]
  • HollkMessage_Embedded* mutable_hollkfuzz(int index):从0开始索引,返回一个index索引处的Embedded对象指针
  • HollkMessage_Embedded* add_hollkfuzz():在字段末尾添加一个新元素并返回一个指向它的指针。返回Bar的值是可变的,并且不会设置任何字段
  • void clear_hollkfuzz():清除字段中所有元素,调用结束后hollkfuzz_size()函数返回0
  • const RepeatedPtrField< ::HollkMessage_Embedded >& hollkfuzz() const:返回存储字段元素的底层的 RepeatedField
  • RepeatedPtrField< ::HollkMessage_Embedded >* mutable_hollkfuzz():返回存储字段元素的底层的 RepeatedField的mutable指针
oneof数值类型字段

前置知识回顾:
1、字段在protobuf进行编译后,字段名称会变成一个形如“k+name”的形式存储为一个常量
2、oneof在C++中相当于Switch case

示例如下:

// Filename:hollk.proto
// Path:3_fields/3_oneof/1_numeric/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    oneof numeric_oneof{
        int32 hollkfuzz = 1;
        int32 hollkafl = 2;
    }
}

下面是编译后的hollk.pb.h部分代码截图

  • bool has_hollkfuzz() const:如果case选中的为kHollkfuzz,则返回true。如果选中的不是kHollkfuzz,则返回false
  • int32 hollkfuzz() const:如果case选中的为kHollkfuzz,则返回该字段的值。如果选中的不是kHollkfuzz,则返回默认值
  • void set_hollkfuzz(int32 value):
    • 如果oneof列表中其他任意字段已经被设置了,则调用clear_numeric_oneof()函数
    • 设置该字段值为value,并设置oneof case为kHollkfuzz
    • has_hollkfuzz()函数返回true,hollkfuzz()函数返回value值,numeric_oneof_case()函数返回kHollkfuzz
  • void clear_hollkfuzz():
    • 如果case选中的不是kHollkfuzz,则不做改变
    • 如果case选中的是kHollkfuzz,则清空该字段值和oneof case。has_hollkfuzz()函数返回false,hollkfuzz()函数返回默认值,numeric_oneof_case()函数返回NUMERIC_ONEOF_NOT_SET关键字
oneof字符串类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/3_oneof/2_string/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    oneof string_oneof{
        string hollkfuzz = 1;
        bytes hollkafl = 2;
    }
}

下面是编译后的hollk.pb.h部分代码截图

  • bool has_hollkfuzz() const:如果case选中的为kHollkfuzz,则返回true。如果选中的不是kHollkfuzz,则返回false
  • const string& hollkfuzz() const:如果case选中的为kHollkfuzz,则返回该字段的值。如果选中的不是kHollkfuzz,则返回默认值
  • void set_hollkfuzz(ArgT0&& arg0, ArgT... args):template自定义参数
    • void set_foo(const string& value):
      • 如果oneof列表中其他任意字段已经被设置了,则调用clear_string_oneof()函数
      • 设置该字段值为value,并设置oneof case为kHollkfuzz
      • has_hollkfuzz()函数返回true,hollkfuzz()函数返回value值,string_oneof_case()函数返回kHollkfuzz
    • void set_foo(const char* value):
      • 如果oneof列表中其他任意字段已经被设置了,则调用clear_string_oneof()函数
      • 使用C语言方式,设置该字段值为以空字节结尾的value字符串,并设置oneof case为kHollkfuzz
      • has_hollkfuzz()函数返回true,hollkfuzz()函数返回value值,string_oneof_case()函数返回kHollkfuzz
    • void set_foo(const char* value, int size):
      • 如果oneof列表中其他任意字段已经被设置了,则调用clear_string_oneof()函数
      • 使用C语言方式,设置该字段值为size长度的value字符串,并设置oneof case为kHollkfuzz
      • has_hollkfuzz()函数返回true,hollkfuzz()函数返回value值,string_oneof_case()函数返回kHollkfuzz
  • string* mutable_hollkfuzz():
    • 如果oneof列表中其他任意字段已经被设置了,则调用clear_string_oneof()函数
    • 将oneof case设置为kHollkfuzz,返回指向存储字段值的可变字符串对象的指针。如果该函数在调用之前oneof case没有被设置为kHollkfuzz,即该字段里面还没有值,则返回NULL(需要注意的是这里不是返回默认值)
    • has_hollkfuzz()函数返回true,hollkfuzz()函数返回写入给定字符串的任何值,string_oneof_case()函数返回kHollkfuzz
  • void clear_hollkfuzz():
    • 如果case选中的不是kHollkfuzz,则不做改变
    • 如果case选中的是kHollkfuzz,则清空该字段值和oneof case。has_hollkfuzz()函数返回false,hollkfuzz()函数返回默认值,string_oneof_case()函数返回STRING_ONEOF_NOT_SET关键字
  • void set_allocated_hollkfuzz(string* hollkfuzz):
    • 调用clear_string_oneof()函数
    • 如果字符串指针不为NULL:将该字段设置为字符串对象,设置oneof case为kHollkfuzz。该字段类型message拥有分配的字符串对象的所有权。has_hollkfuzz()函数返回true,string_oneof_case()函数返回kHollkfuzz
    • 如果字符串指针为NULL:has_hollkfuzz()函数返回false,string_oneof_case()函数返回STRING_ONEOF_NOT_SET关键字
  • string* release_hollkfuzz():
    • 如果oneof case不为kHollkfuzz,则返回NULL
    • 清空oneof case,释放该字段的所有权,并返回字符串对象的指针。在调用该函数后,调用者获取分配的字符串对象的所有权。has_hollkfuzz()函数返回false,hollkfuzz()函数返回默认值,string_oneof_case()函数返回STRING_ONEOF_NOT_SET关键字
oneof枚举类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/3_oneof/3_enum/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    enum Option{
        CORPUS = 0;
        FUZZER = 1;
    }
    oneof enum_oneof{
        Option hollkfuzz = 1;
        Option hollkafl = 2;
    }
}

下面是编译后的hollk.pb.h部分代码截图

  • bool has_hollkfuzz() const:如果case选中的为kHollkfuzz,则返回true。如果选中的不是kHollkfuzz,则返回false
  • HollkMessage_Option hollkfuzz() const:如果case选中的为kHollkfuzz,则返回该字段的值。如果选中的不是kHollkfuzz,则返回默认值
  • void set_hollkfuzz(HollkMessage_Option value):
    • 如果oneof列表中其他任意字段已经被设置了,则调用clear_enum_oneof()函数
    • 设置该字段值为value,并设置oneof case为kHollkfuzz
    • has_hollkfuzz()函数返回true,hollkfuzz()函数返回value值,enum_oneof_case()函数返回kHollkfuzz
  • void clear_hollkfuzz():
    • 如果case选中的不是kHollkfuzz,则不做改变
    • 如果case选中的是kHollkfuzz,则清空该字段值和oneof case。has_hollkfuzz()函数返回false,hollkfuzz()函数返回默认值,enum_oneof_case()函数返回ENUM_ONEOF_NOT_SET关键字
oneof message嵌套类型字段

示例如下:

// Filename:hollk.proto
// Path:3_fields/3_oneof/4_embedded/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    message Embedded{}

    oneof emb_oneof{
        Embedded hollkfuzz = 1;
        Embedded hollkafl = 2;
    }
}

下面是编译后的hollk.pb.h部分代码截图

  • bool has_hollkfuzz() const:如果case选中的为kHollkfuzz,则返回true。如果选中的不是kHollkfuzz,则返回false
  • const HollkMessage_Embedded& hollkfuzz() const:如果case选中的为kHollkfuzz,则返回该字段的值。如果选中的不是kHollkfuzz,则返回Embedded::default_instance()函数
  • HollkMessage_Embedded* mutable_hollkfuzz():
    • 如果oneof列表中其他任意字段已经被设置了,则调用clear_emb_oneof()函数
    • 将oneof case设置为kHollkfuzz,返回存储字段值的可变Embedded对象的指针。如果oneof case在调用该函数之前不是kHollkfuzz,即没有对该字段做赋值操作,则返回的Embedded不会设置字段
    • 调用该函数后has_hollkfuzz()返回true,hollkfuzz()返回同一Embedded实例的引用,emb_oneof_case()返回kHollkfuzz
  • void clear_hollkfuzz():
    • 如果case选中的不是kHollkfuzz,则不做改变
    • 如果case选中的是kHollkfuzz,则清空该字段值和oneof case。has_hollkfuzz()函数返回false,hollkfuzz()函数返回默认值,emb_oneof_case()函数返回EMB_ONEOF_NOT_SET关键字
  • void set_allocated_hollkfuzz(HollkMessage_Embedded* hollkfuzz):
    • 调用clear_emb_oneof()函数
    • 如果Embedded指针不为NULL:将该字段设置为Embedded对象,设置oneof case为kHollkfuzz。message获得分配Embedded对象的所有权,has_hollkfuzz()返回true,emb_oneof_case()返回kHollkfuzz
    • 如果Embedded指针为NULL:has_hollkfuzz()返回false,emb_oneof_case()返回EMB_ONEOF_NOT_SET关键字(类似调用clear_emb_oneof())
  • HollkMessage_Embedded* release_hollkfuzz():
    • 如果oneof case不是kHollkfuzz,则返回NULL
    • 如果oneof case是kHollkfuzz,清空oneof case,释放字段的所有权并返回Embedded对象指针。调用者重新获得分配Embedded对象的所有权,has_hollkfuzz()返回false,hollkfuzz()返回默认值,emb_oneof_case()返回EMB_ONEOF_NOT_SET关键字
Oneof

示例如下:

// Filename:hollk.proto
// Path:4_oneof/
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    oneof numeric_oneof{
        int32 hollkfuzz = 1;
        string hollkafl = 2;
    }
}

编译器将会生成如下的C++枚举类型

同时还会生成一下方法:

  • NumericOneofCase numeric_oneof_case() const:返回指出哪个字段已经被设置了,如果没有设置,则返回NUMERIC_ONEOF_NOT_SET关键字
  • void clear_numeric_oneof():如果其中一个字段集使用了指针,则释放该对象,将oneof case设置为NUMERIC_ONEOF_NOT_SET关键字
Enum

示例如下:

// Filename:hollk.proto
// Path:5_enum
// Command:$HOME/libprotobuf-mutator/build/external.protobuf/bin/protoc-3.17.3.0 ./hollknest.proto --cpp_out=./
syntax = "proto2";

package HollkProtoTest;

message HollkMessage{
    enum Option{
        CORPUS = 0;
        FUZZER = 1;
        TARGET = 3;
    }
    optional Option hollkfuzz = 1;
}

编译器在创建C++枚举类型的同时,还会创建如下函数:

  • bool Option_IsValid(int value):如果给定的数值与Option定义的值之一匹配,则返回true。例如示例中设置为0、1、2,则返回true
  • Option Option_MIN:枚举的最小有效值(示例中为 CORPUS)
    • constexpr HollkMessage_Option HollkMessage_Option_Option_MIN = HollkMessage_Option_CORPUS
  • Option Option_MAX:枚举的最大有效值(示例中为 TARGET)
    • constexpr HollkMessage_Option HollkMessage_Option_Option_MAX = HollkMessage_Option_TARGET
  • const int Option_ARRAYSIZE:Option_MAX + 1
    • constexpr int HollkMessage_Option_Option_ARRAYSIZE = HollkMessage_Option_Option_MAX + 1
  • const EnumDescriptor* Option_descriptor():返回类型的描述符,其中包含有关此枚举类型定义的值的信息
  • const string& Option_Name(T enum_t_value):返回给定数值value的名称。如果不存在value值,则返回一个空字符串。如果多个值具有该value编号,则返回第一个定义的值。例如:示例中Option_Name(3)将返回TARGET
  • bool Option_Parse(ConstStringParam name, Option* value):如果name为该枚举中的一个有效值得名称,则将该名称对应的数值赋值给value。成功返回true,失败返回false。例如:示例中Option_Parse(“FUZZER”, &flip),那么就会将flip设置为1

参考链接:

  • https://developers.google.com/protocol-buffers/docs/reference/cpp-generated
交个朋友吧~

扫描下方微信二维码,一起讨论研究

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/868914.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号