在上一篇【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
在.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()函数返回默认值
示例如下:
// 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指针
示例如下:
// 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指针
前置知识回顾:
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关键字
示例如下:
// 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
- void set_foo(const string& value):
- 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关键字
示例如下:
// 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关键字
示例如下:
// 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关键字
示例如下:
// 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关键字
示例如下:
// 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
交个朋友吧~扫描下方微信二维码,一起讨论研究



