Prevent UBSAN from complaining too early about invalid enums
This is making reproducing https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15052 difficult. Docs-Preview: https://skia.org/?cl=217457 Change-Id: I131e8c1b64f621178696b94b63bd09513ca6c170 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/217457 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
parent
a718813e2a
commit
00587e32b8
17
fuzz/Fuzz.h
17
fuzz/Fuzz.h
@ -58,6 +58,10 @@ public:
|
||||
template <typename T, typename Min, typename Max>
|
||||
void nextRange(T*, Min, Max);
|
||||
|
||||
// nextEnum is a wrapper around nextRange for enums.
|
||||
template <typename T>
|
||||
void nextEnum(T* ptr, T max);
|
||||
|
||||
// nextN loads n * sizeof(T) bytes into ptr
|
||||
template <typename T>
|
||||
void nextN(T* ptr, int n);
|
||||
@ -99,6 +103,19 @@ inline void Fuzz::nextRange(T* value, Min min, Max max) {
|
||||
if (*value > (T)max) { *value = (T)max; }
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Fuzz::nextEnum(T* value, T max) {
|
||||
// This works around the fact that UBSAN will assert if we put an invalid
|
||||
// value into an enum. We might see issues with enums being represented
|
||||
// on Windows differently than Linux, but that's not a thing we can fix here.
|
||||
using U = typename std::underlying_type<T>::type;
|
||||
U v;
|
||||
this->next(&v);
|
||||
if (v < (U)0) { *value = (T)0; return;}
|
||||
if (v > (U)max) { *value = (T)max; return;}
|
||||
*value = (T)v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Fuzz::nextN(T* ptr, int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
@ -114,7 +114,7 @@ static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
|
||||
SkColor color;
|
||||
SkBlendMode mode;
|
||||
fuzz->next(&color);
|
||||
fuzz->nextRange(&mode, 0, SkBlendMode::kLastMode);
|
||||
fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
|
||||
return SkColorFilters::Blend(color, mode);
|
||||
}
|
||||
case 2: {
|
||||
@ -210,8 +210,8 @@ static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
||||
return SkShaders::Color(color);
|
||||
case 3:
|
||||
img = make_fuzz_image(fuzz);
|
||||
fuzz->nextRange(&tmX, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextRange(&tmY, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
|
||||
fuzz->next(&useMatrix);
|
||||
if (useMatrix) {
|
||||
FuzzNiceMatrix(fuzz, &matrix);
|
||||
@ -219,8 +219,8 @@ static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
||||
return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
|
||||
case 4:
|
||||
bitmap = make_fuzz_bitmap(fuzz);
|
||||
fuzz->nextRange(&tmX, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextRange(&tmY, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
|
||||
fuzz->next(&useMatrix);
|
||||
if (useMatrix) {
|
||||
FuzzNiceMatrix(fuzz, &matrix);
|
||||
@ -237,14 +237,14 @@ static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
||||
case 7:
|
||||
shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
|
||||
shader2 = make_fuzz_shader(fuzz, depth - 1);
|
||||
fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
|
||||
fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
|
||||
return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
|
||||
case 8: {
|
||||
auto pic = make_fuzz_picture(fuzz, depth - 1);
|
||||
bool useTile;
|
||||
SkRect tile;
|
||||
fuzz->nextRange(&tmX, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextRange(&tmY, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
|
||||
fuzz->next(&useMatrix, &useTile);
|
||||
if (useMatrix) {
|
||||
FuzzNiceMatrix(fuzz, &matrix);
|
||||
@ -268,7 +268,7 @@ static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
||||
fuzz->nextN(pts, 2);
|
||||
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
||||
fuzz->nextN(colors, colorCount);
|
||||
fuzz->nextRange(&tmX, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
||||
fuzz->next(&useMatrix, &usePos);
|
||||
if (useMatrix) {
|
||||
FuzzNiceMatrix(fuzz, &matrix);
|
||||
@ -287,7 +287,7 @@ static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
||||
bool usePos;
|
||||
SkColor colors[kMaxColors];
|
||||
SkScalar pos[kMaxColors];
|
||||
fuzz->nextRange(&tmX, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
||||
fuzz->next(&useMatrix, &usePos, ¢er, &radius);
|
||||
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
||||
fuzz->nextN(colors, colorCount);
|
||||
@ -308,7 +308,7 @@ static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
||||
bool usePos;
|
||||
SkColor colors[kMaxColors];
|
||||
SkScalar pos[kMaxColors];
|
||||
fuzz->nextRange(&tmX, 0, SkTileMode::kLastTileMode);
|
||||
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
||||
fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
|
||||
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
||||
fuzz->nextN(colors, colorCount);
|
||||
@ -394,7 +394,7 @@ static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
|
||||
SkScalar advance, phase;
|
||||
fuzz->next(&advance, &phase);
|
||||
SkPath1DPathEffect::Style style;
|
||||
fuzz->nextRange(&style, 0, SkPath1DPathEffect::kLastEnum_Style);
|
||||
fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
|
||||
return SkPath1DPathEffect::Make(path, advance, phase, style);
|
||||
}
|
||||
case 4: {
|
||||
@ -445,7 +445,7 @@ static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
|
||||
return nullptr;
|
||||
case 1: {
|
||||
SkBlurStyle blurStyle;
|
||||
fuzz->nextRange(&blurStyle, 0, kLastEnum_SkBlurStyle);
|
||||
fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
|
||||
SkScalar sigma;
|
||||
fuzz->next(&sigma);
|
||||
bool respectCTM;
|
||||
@ -562,7 +562,7 @@ static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
|
||||
SkMatrix matrix;
|
||||
FuzzNiceMatrix(fuzz, &matrix);
|
||||
SkFilterQuality quality;
|
||||
fuzz->nextRange(&quality, 0, SkFilterQuality::kLast_SkFilterQuality);
|
||||
fuzz->nextEnum(&quality, SkFilterQuality::kLast_SkFilterQuality);
|
||||
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
||||
return SkImageFilter::MakeMatrixFilter(matrix, quality, std::move(input));
|
||||
}
|
||||
@ -651,7 +651,7 @@ static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
|
||||
SkRect srcRect, dstRect;
|
||||
SkFilterQuality filterQuality;
|
||||
fuzz->next(&srcRect, &dstRect);
|
||||
fuzz->nextRange(&filterQuality, 0, SkFilterQuality::kLast_SkFilterQuality);
|
||||
fuzz->nextEnum(&filterQuality, SkFilterQuality::kLast_SkFilterQuality);
|
||||
return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
|
||||
}
|
||||
case 11:
|
||||
@ -683,7 +683,7 @@ static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
|
||||
bool convolveAlpha, useCropRect;
|
||||
fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
|
||||
SkMatrixConvolutionImageFilter::TileMode tileMode;
|
||||
fuzz->nextRange(&tileMode, 0, SkMatrixConvolutionImageFilter::TileMode::kLast_TileMode);
|
||||
fuzz->nextEnum(&tileMode, SkMatrixConvolutionImageFilter::TileMode::kLast_TileMode);
|
||||
SkImageFilter::CropRect cropRect;
|
||||
if (useCropRect) {
|
||||
fuzz->next(&cropRect);
|
||||
@ -791,7 +791,7 @@ static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
|
||||
SkBlendMode blendMode;
|
||||
bool useCropRect;
|
||||
fuzz->next(&useCropRect);
|
||||
fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
|
||||
fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
|
||||
SkImageFilter::CropRect cropRect;
|
||||
if (useCropRect) {
|
||||
fuzz->next(&cropRect);
|
||||
@ -843,10 +843,10 @@ static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
template <typename T, typename Min, typename Max>
|
||||
inline T make_fuzz_t_range(Fuzz* fuzz, Min minv, Max maxv) {
|
||||
template <typename T>
|
||||
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
|
||||
T value;
|
||||
fuzz->nextRange(&value, minv, maxv);
|
||||
fuzz->nextEnum(&value, maxv);
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -858,9 +858,10 @@ static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
|
||||
paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
|
||||
paint->setDither( make_fuzz_t<bool>(fuzz));
|
||||
paint->setColor( make_fuzz_t<SkColor>(fuzz));
|
||||
paint->setBlendMode( make_fuzz_t_range<SkBlendMode>(fuzz, 0, SkBlendMode::kLastMode));
|
||||
paint->setFilterQuality(make_fuzz_t_range<SkFilterQuality>(fuzz, 0, kLast_SkFilterQuality));
|
||||
paint->setStyle( make_fuzz_t_range<SkPaint::Style>(fuzz, 0, 2));
|
||||
paint->setBlendMode( make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
|
||||
paint->setFilterQuality(make_fuzz_enum_range<SkFilterQuality>(fuzz, kLast_SkFilterQuality));
|
||||
paint->setStyle( make_fuzz_enum_range<SkPaint::Style>(fuzz,
|
||||
SkPaint::Style::kStrokeAndFill_Style));
|
||||
paint->setShader( make_fuzz_shader(fuzz, depth - 1));
|
||||
paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
|
||||
paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
|
||||
@ -870,8 +871,8 @@ static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
|
||||
if (paint->getStyle() != SkPaint::kFill_Style) {
|
||||
paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
|
||||
paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
|
||||
paint->setStrokeCap( make_fuzz_t_range<SkPaint::Cap>(fuzz, 0, SkPaint::kLast_Cap));
|
||||
paint->setStrokeJoin( make_fuzz_t_range<SkPaint::Join>(fuzz, 0, SkPaint::kLast_Join));
|
||||
paint->setStrokeCap( make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
|
||||
paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,14 +887,14 @@ static SkFont fuzz_font(Fuzz* fuzz) {
|
||||
font.setEmbeddedBitmaps( make_fuzz_t<bool>(fuzz));
|
||||
font.setForceAutoHinting( make_fuzz_t<bool>(fuzz));
|
||||
font.setEmbolden( make_fuzz_t<bool>(fuzz));
|
||||
font.setHinting( make_fuzz_t_range<SkFontHinting>(fuzz, 0, SkFontHinting::kFull));
|
||||
font.setEdging( make_fuzz_t_range<SkFont::Edging>(fuzz, 0,
|
||||
(int)SkFont::Edging::kSubpixelAntiAlias));
|
||||
font.setHinting( make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
|
||||
font.setEdging( make_fuzz_enum_range<SkFont::Edging>(fuzz,
|
||||
SkFont::Edging::kSubpixelAntiAlias));
|
||||
return font;
|
||||
}
|
||||
|
||||
static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
|
||||
return make_fuzz_t_range<SkTextEncoding>(fuzz, 0, 3);
|
||||
return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
|
||||
}
|
||||
|
||||
constexpr int kMaxGlyphCount = 30;
|
||||
|
@ -4,6 +4,15 @@ Reproducing Skia Fuzzes
|
||||
We assume that you can [build Skia](/user/build). Many fuzzes only reproduce
|
||||
when building with ASAN or MSAN; see [those instructions for more details](./xsan).
|
||||
|
||||
When building, you should add the following args to BUILD.gn to make reproducing
|
||||
less machine- and platform- dependent:
|
||||
|
||||
skia_use_fontconfig=false
|
||||
skia_use_freetype=true
|
||||
skia_use_system_freetype2=false
|
||||
skia_use_wuffs=true
|
||||
skia_enable_skottie=true
|
||||
|
||||
All that is needed to reproduce a fuzz downloaded from ClusterFuzz, oss-fuzz or
|
||||
fuzzer.skia.org is to run something like:
|
||||
|
||||
@ -18,4 +27,4 @@ the name of the testcase. Manually providing type and name is also supported, li
|
||||
To enumerate all supported types and names, run the following:
|
||||
|
||||
out/ASAN/fuzz --help # will list all types
|
||||
out/ASAN/fuzz -t api # will list all names
|
||||
out/ASAN/fuzz -t api # will list all names
|
||||
|
Loading…
Reference in New Issue
Block a user