2016-01-13 20:57:57 +00:00
/*
* Copyright 2016 Google Inc .
*
* Use of this source code is governed by a BSD - style license that can be
* found in the LICENSE file .
*/
# include "Fuzz.h"
2016-01-21 13:03:28 +00:00
# include "SkCanvas.h"
# include "SkCodec.h"
2016-01-15 14:19:53 +00:00
# include "SkCommandLineFlags.h"
2016-01-21 13:03:28 +00:00
# include "SkData.h"
# include "SkImage.h"
# include "SkImageEncoder.h"
# include "SkMallocPixelRef.h"
2017-01-06 18:48:19 +00:00
# include "SkPath.h"
2017-01-06 13:26:56 +00:00
# include "SkOSFile.h"
# include "SkOSPath.h"
2016-07-19 23:50:03 +00:00
# include "SkPicture.h"
2016-11-11 20:16:46 +00:00
# if SK_SUPPORT_GPU
2016-10-18 17:06:24 +00:00
# include "SkSLCompiler.h"
2016-11-11 20:16:46 +00:00
# endif
2016-01-21 13:03:28 +00:00
# include "SkStream.h"
2016-01-15 13:46:54 +00:00
# include <signal.h>
2016-01-15 14:19:53 +00:00
2016-11-23 15:55:18 +00:00
# include "sk_tool_utils.h"
2017-01-06 13:26:56 +00:00
DEFINE_string2 ( bytes , b , " " , " A path to a file or a directory. If a file, the contents will be used as the fuzz bytes. If a directory, all files in the directory will be used as fuzz bytes for the fuzzer, one at a time. " ) ;
2016-01-21 14:13:52 +00:00
DEFINE_string2 ( name , n , " " , " If --type is 'api', fuzz the API with this name. " ) ;
2016-01-21 13:03:28 +00:00
2016-06-09 14:15:12 +00:00
DEFINE_string2 ( type , t , " api " , " How to interpret --bytes, either 'image_scale', 'image_mode', 'skp', 'icc', or 'api'. " ) ;
2016-02-17 00:14:23 +00:00
DEFINE_string2 ( dump , d , " " , " If not empty, dump 'image*' or 'skp' types as a PNG with this name. " ) ;
2016-01-21 13:03:28 +00:00
2017-01-06 13:26:56 +00:00
static int printUsage ( ) {
SkDebugf ( " Usage: fuzz -t <type> -b <path/to/file> [-n api-to-fuzz] \n " ) ;
2016-01-21 13:03:28 +00:00
return 1 ;
}
2017-01-06 13:26:56 +00:00
static int fuzz_file ( const char * path ) ;
2016-02-17 00:14:23 +00:00
static uint8_t calculate_option ( SkData * ) ;
2016-01-21 13:03:28 +00:00
2017-01-06 13:26:56 +00:00
static void fuzz_api ( sk_sp < SkData > ) ;
static void fuzz_img ( sk_sp < SkData > , uint8_t , uint8_t ) ;
static void fuzz_skp ( sk_sp < SkData > ) ;
static void fuzz_icc ( sk_sp < SkData > ) ;
static void fuzz_color_deserialize ( sk_sp < SkData > ) ;
2017-01-06 18:48:19 +00:00
static void fuzz_path_deserialize ( sk_sp < SkData > ) ;
2016-11-11 20:16:46 +00:00
# if SK_SUPPORT_GPU
2017-01-06 13:26:56 +00:00
static void fuzz_sksl2glsl ( sk_sp < SkData > ) ;
2016-11-11 20:16:46 +00:00
# endif
2016-01-13 20:57:57 +00:00
int main ( int argc , char * * argv ) {
2016-01-15 14:19:53 +00:00
SkCommandLineFlags : : Parse ( argc , argv ) ;
2016-01-15 15:56:20 +00:00
const char * path = FLAGS_bytes . isEmpty ( ) ? argv [ 0 ] : FLAGS_bytes [ 0 ] ;
2017-01-06 13:26:56 +00:00
if ( ! sk_isdir ( path ) ) {
return fuzz_file ( path ) ;
}
SkOSFile : : Iter it ( path ) ;
for ( SkString file ; it . next ( & file ) ; ) {
SkString p = SkOSPath : : Join ( path , file . c_str ( ) ) ;
SkDebugf ( " Fuzzing %s \n " , p . c_str ( ) ) ;
int rv = fuzz_file ( p . c_str ( ) ) ;
if ( rv ! = 0 ) {
return rv ;
}
}
return 0 ;
}
static int fuzz_file ( const char * path ) {
2016-08-02 21:40:46 +00:00
sk_sp < SkData > bytes ( SkData : : MakeFromFileName ( path ) ) ;
2016-01-21 13:03:28 +00:00
if ( ! bytes ) {
SkDebugf ( " Could not read %s \n " , path ) ;
2017-01-06 13:26:56 +00:00
return 1 ;
2016-01-21 13:03:28 +00:00
}
2016-01-13 20:57:57 +00:00
2016-08-02 21:40:46 +00:00
uint8_t option = calculate_option ( bytes . get ( ) ) ;
2016-02-17 00:14:23 +00:00
2016-01-21 14:13:52 +00:00
if ( ! FLAGS_type . isEmpty ( ) ) {
2016-10-18 17:06:24 +00:00
if ( 0 = = strcmp ( " api " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_api ( bytes ) ;
return 0 ;
2016-10-18 17:06:24 +00:00
}
if ( 0 = = strcmp ( " color_deserialize " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_color_deserialize ( bytes ) ;
return 0 ;
2016-10-18 17:06:24 +00:00
}
if ( 0 = = strcmp ( " icc " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_icc ( bytes ) ;
return 0 ;
2016-10-18 17:06:24 +00:00
}
if ( 0 = = strcmp ( " image_scale " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_img ( bytes , option , 0 ) ;
return 0 ;
2016-10-18 17:06:24 +00:00
}
if ( 0 = = strcmp ( " image_mode " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_img ( bytes , 0 , option ) ;
return 0 ;
2016-10-18 17:06:24 +00:00
}
2017-01-06 18:48:19 +00:00
if ( 0 = = strcmp ( " path_deserialize " , FLAGS_type [ 0 ] ) ) {
fuzz_path_deserialize ( bytes ) ;
return 0 ;
}
2016-10-18 17:06:24 +00:00
if ( 0 = = strcmp ( " skp " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_skp ( bytes ) ;
return 0 ;
2016-10-18 17:06:24 +00:00
}
2016-11-11 20:16:46 +00:00
# if SK_SUPPORT_GPU
2016-10-18 17:06:24 +00:00
if ( 0 = = strcmp ( " sksl2glsl " , FLAGS_type [ 0 ] ) ) {
2017-01-06 13:26:56 +00:00
fuzz_sksl2glsl ( bytes ) ;
return 0 ;
2016-01-21 14:13:52 +00:00
}
2016-11-11 20:16:46 +00:00
# endif
2016-01-21 13:03:28 +00:00
}
2017-01-06 13:26:56 +00:00
return printUsage ( ) ;
2016-01-21 13:03:28 +00:00
}
2016-02-17 00:14:23 +00:00
// This adds up the first 1024 bytes and returns it as an 8 bit integer. This allows afl-fuzz to
// deterministically excercise different paths, or *options* (such as different scaling sizes or
// different image modes) without needing to introduce a parameter. This way we don't need a
// image_scale1, image_scale2, image_scale4, etc fuzzer, we can just have a image_scale fuzzer.
// Clients are expected to transform this number into a different range, e.g. with modulo (%).
static uint8_t calculate_option ( SkData * bytes ) {
uint8_t total = 0 ;
const uint8_t * data = bytes - > bytes ( ) ;
for ( size_t i = 0 ; i < 1024 & & i < bytes - > size ( ) ; i + + ) {
total + = data [ i ] ;
}
return total ;
}
2017-01-06 13:26:56 +00:00
static void fuzz_api ( sk_sp < SkData > bytes ) {
2016-01-21 14:13:52 +00:00
const char * name = FLAGS_name . isEmpty ( ) ? " " : FLAGS_name [ 0 ] ;
2016-01-13 20:57:57 +00:00
for ( auto r = SkTRegistry < Fuzzable > : : Head ( ) ; r ; r = r - > next ( ) ) {
auto fuzzable = r - > factory ( ) ;
2016-01-21 14:13:52 +00:00
if ( 0 = = strcmp ( name , fuzzable . name ) ) {
2016-01-15 14:19:53 +00:00
SkDebugf ( " Fuzzing %s... \n " , fuzzable . name ) ;
Fuzz fuzz ( bytes ) ;
2016-01-13 20:57:57 +00:00
fuzzable . fn ( & fuzz ) ;
2016-02-01 16:23:50 +00:00
SkDebugf ( " [terminated] Success! \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-01-13 20:57:57 +00:00
}
}
2016-01-21 14:13:52 +00:00
SkDebugf ( " When using --type api, please choose an API to fuzz with --name/-n: \n " ) ;
for ( auto r = SkTRegistry < Fuzzable > : : Head ( ) ; r ; r = r - > next ( ) ) {
auto fuzzable = r - > factory ( ) ;
SkDebugf ( " \t %s \n " , fuzzable . name ) ;
}
2016-01-21 13:03:28 +00:00
}
static void dump_png ( SkBitmap bitmap ) {
if ( ! FLAGS_dump . isEmpty ( ) ) {
2016-11-23 15:55:18 +00:00
sk_tool_utils : : EncodeImageToFile ( FLAGS_dump [ 0 ] , bitmap , SkEncodedImageFormat : : kPNG , 100 ) ;
2016-01-21 13:03:28 +00:00
SkDebugf ( " Dumped to %s \n " , FLAGS_dump [ 0 ] ) ;
}
}
2017-01-06 13:26:56 +00:00
static void fuzz_img ( sk_sp < SkData > bytes , uint8_t scale , uint8_t mode ) {
2016-02-17 00:14:23 +00:00
// We can scale 1x, 2x, 4x, 8x, 16x
scale = scale % 5 ;
2016-02-18 14:27:38 +00:00
float fscale = ( float ) pow ( 2.0f , scale ) ;
SkDebugf ( " Scaling factor: %f \n " , fscale ) ;
2016-02-17 00:14:23 +00:00
2016-12-08 14:07:56 +00:00
// We have 5 different modes of decoding.
mode = mode % 5 ;
2016-02-17 00:14:23 +00:00
SkDebugf ( " Mode: %d \n " , mode ) ;
// This is mostly copied from DMSrcSink's CodecSrc::draw method.
2016-02-01 16:23:50 +00:00
SkDebugf ( " Decoding \n " ) ;
2016-11-03 18:40:50 +00:00
std : : unique_ptr < SkCodec > codec ( SkCodec : : NewFromData ( bytes ) ) ;
2016-01-21 13:03:28 +00:00
if ( nullptr = = codec . get ( ) ) {
2016-02-01 16:23:50 +00:00
SkDebugf ( " [terminated] Couldn't create codec. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-01-21 13:03:28 +00:00
}
SkImageInfo decodeInfo = codec - > getInfo ( ) ;
2016-12-08 14:07:56 +00:00
if ( 4 = = mode & & decodeInfo . colorType ( ) = = kIndex_8_SkColorType ) {
// 4 means animated. Frames beyond the first cannot be decoded to
// index 8.
decodeInfo = decodeInfo . makeColorType ( kN32_SkColorType ) ;
}
2016-02-17 00:14:23 +00:00
SkISize size = codec - > getScaledDimensions ( fscale ) ;
decodeInfo = decodeInfo . makeWH ( size . width ( ) , size . height ( ) ) ;
2016-01-21 13:03:28 +00:00
// Construct a color table for the decode if necessary
2016-11-04 17:02:54 +00:00
sk_sp < SkColorTable > colorTable ( nullptr ) ;
2016-01-21 13:03:28 +00:00
SkPMColor * colorPtr = nullptr ;
int * colorCountPtr = nullptr ;
int maxColors = 256 ;
if ( kIndex_8_SkColorType = = decodeInfo . colorType ( ) ) {
SkPMColor colors [ 256 ] ;
colorTable . reset ( new SkColorTable ( colors , maxColors ) ) ;
colorPtr = const_cast < SkPMColor * > ( colorTable - > readColors ( ) ) ;
colorCountPtr = & maxColors ;
}
SkBitmap bitmap ;
SkMallocPixelRef : : ZeroedPRFactory zeroFactory ;
SkCodec : : Options options ;
options . fZeroInitialized = SkCodec : : kYes_ZeroInitialized ;
2016-02-17 00:14:23 +00:00
if ( ! bitmap . tryAllocPixels ( decodeInfo , & zeroFactory , colorTable . get ( ) ) ) {
2016-02-01 16:23:50 +00:00
SkDebugf ( " [terminated] Could not allocate memory. Image might be too large (%d x %d) " ,
2016-02-17 00:14:23 +00:00
decodeInfo . width ( ) , decodeInfo . height ( ) ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-01-21 13:03:28 +00:00
}
2016-02-17 00:14:23 +00:00
switch ( mode ) {
case 0 : { //kCodecZeroInit_Mode, kCodec_Mode
switch ( codec - > getPixels ( decodeInfo , bitmap . getPixels ( ) , bitmap . rowBytes ( ) , & options ,
colorPtr , colorCountPtr ) ) {
case SkCodec : : kSuccess :
SkDebugf ( " [terminated] Success! \n " ) ;
break ;
case SkCodec : : kIncompleteInput :
SkDebugf ( " [terminated] Partial Success \n " ) ;
break ;
case SkCodec : : kInvalidConversion :
SkDebugf ( " Incompatible colortype conversion \n " ) ;
// Crash to allow afl-fuzz to know this was a bug.
raise ( SIGSEGV ) ;
default :
SkDebugf ( " [terminated] Couldn't getPixels. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
break ;
}
case 1 : { //kScanline_Mode
if ( SkCodec : : kSuccess ! = codec - > startScanlineDecode ( decodeInfo , NULL , colorPtr ,
colorCountPtr ) ) {
SkDebugf ( " [terminated] Could not start scanline decoder \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
void * dst = bitmap . getAddr ( 0 , 0 ) ;
size_t rowBytes = bitmap . rowBytes ( ) ;
uint32_t height = decodeInfo . height ( ) ;
switch ( codec - > getScanlineOrder ( ) ) {
case SkCodec : : kTopDown_SkScanlineOrder :
case SkCodec : : kBottomUp_SkScanlineOrder :
// We do not need to check the return value. On an incomplete
// image, memory will be filled with a default value.
codec - > getScanlines ( dst , height , rowBytes ) ;
break ;
}
2016-02-01 16:23:50 +00:00
SkDebugf ( " [terminated] Success! \n " ) ;
2016-01-21 13:03:28 +00:00
break ;
2016-02-17 00:14:23 +00:00
}
case 2 : { //kStripe_Mode
const int height = decodeInfo . height ( ) ;
// This value is chosen arbitrarily. We exercise more cases by choosing a value that
// does not align with image blocks.
const int stripeHeight = 37 ;
const int numStripes = ( height + stripeHeight - 1 ) / stripeHeight ;
// Decode odd stripes
if ( SkCodec : : kSuccess ! = codec - > startScanlineDecode ( decodeInfo , NULL , colorPtr ,
colorCountPtr )
| | SkCodec : : kTopDown_SkScanlineOrder ! = codec - > getScanlineOrder ( ) ) {
// This mode was designed to test the new skip scanlines API in libjpeg-turbo.
// Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
// to run this test for image types that do not have this scanline ordering.
SkDebugf ( " [terminated] Could not start top-down scanline decoder \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
for ( int i = 0 ; i < numStripes ; i + = 2 ) {
// Skip a stripe
const int linesToSkip = SkTMin ( stripeHeight , height - i * stripeHeight ) ;
codec - > skipScanlines ( linesToSkip ) ;
// Read a stripe
const int startY = ( i + 1 ) * stripeHeight ;
const int linesToRead = SkTMin ( stripeHeight , height - startY ) ;
if ( linesToRead > 0 ) {
codec - > getScanlines ( bitmap . getAddr ( 0 , startY ) , linesToRead , bitmap . rowBytes ( ) ) ;
}
}
// Decode even stripes
const SkCodec : : Result startResult = codec - > startScanlineDecode ( decodeInfo , nullptr ,
colorPtr , colorCountPtr ) ;
if ( SkCodec : : kSuccess ! = startResult ) {
SkDebugf ( " [terminated] Failed to restart scanline decoder with same parameters. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
for ( int i = 0 ; i < numStripes ; i + = 2 ) {
// Read a stripe
const int startY = i * stripeHeight ;
const int linesToRead = SkTMin ( stripeHeight , height - startY ) ;
codec - > getScanlines ( bitmap . getAddr ( 0 , startY ) , linesToRead , bitmap . rowBytes ( ) ) ;
// Skip a stripe
const int linesToSkip = SkTMin ( stripeHeight , height - ( i + 1 ) * stripeHeight ) ;
if ( linesToSkip > 0 ) {
codec - > skipScanlines ( linesToSkip ) ;
}
}
SkDebugf ( " [terminated] Success! \n " ) ;
2016-01-21 13:03:28 +00:00
break ;
2016-02-17 00:14:23 +00:00
}
case 3 : { //kSubset_Mode
// Arbitrarily choose a divisor.
int divisor = 2 ;
// Total width/height of the image.
const int W = codec - > getInfo ( ) . width ( ) ;
const int H = codec - > getInfo ( ) . height ( ) ;
if ( divisor > W | | divisor > H ) {
SkDebugf ( " [terminated] Cannot codec subset: divisor %d is too big "
" with dimensions (%d x %d) \n " , divisor , W , H ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
// subset dimensions
// SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
const int w = SkAlign2 ( W / divisor ) ;
const int h = SkAlign2 ( H / divisor ) ;
SkIRect subset ;
SkCodec : : Options opts ;
opts . fSubset = & subset ;
SkBitmap subsetBm ;
// We will reuse pixel memory from bitmap.
void * pixels = bitmap . getPixels ( ) ;
// Keep track of left and top (for drawing subsetBm into canvas). We could use
// fscale * x and fscale * y, but we want integers such that the next subset will start
// where the last one ended. So we'll add decodeInfo.width() and height().
int left = 0 ;
for ( int x = 0 ; x < W ; x + = w ) {
int top = 0 ;
for ( int y = 0 ; y < H ; y + = h ) {
// Do not make the subset go off the edge of the image.
const int preScaleW = SkTMin ( w , W - x ) ;
const int preScaleH = SkTMin ( h , H - y ) ;
subset . setXYWH ( x , y , preScaleW , preScaleH ) ;
// And fscale
// FIXME: Should we have a version of getScaledDimensions that takes a subset
// into account?
decodeInfo = decodeInfo . makeWH (
SkTMax ( 1 , SkScalarRoundToInt ( preScaleW * fscale ) ) ,
SkTMax ( 1 , SkScalarRoundToInt ( preScaleH * fscale ) ) ) ;
size_t rowBytes = decodeInfo . minRowBytes ( ) ;
if ( ! subsetBm . installPixels ( decodeInfo , pixels , rowBytes , colorTable . get ( ) ,
nullptr , nullptr ) ) {
SkDebugf ( " [terminated] Could not install pixels. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
const SkCodec : : Result result = codec - > getPixels ( decodeInfo , pixels , rowBytes ,
& opts , colorPtr , colorCountPtr ) ;
switch ( result ) {
case SkCodec : : kSuccess :
case SkCodec : : kIncompleteInput :
SkDebugf ( " okay \n " ) ;
break ;
case SkCodec : : kInvalidConversion :
if ( 0 = = ( x | y ) ) {
// First subset is okay to return unimplemented.
SkDebugf ( " [terminated] Incompatible colortype conversion \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
// If the first subset succeeded, a later one should not fail.
// fall through to failure
case SkCodec : : kUnimplemented :
if ( 0 = = ( x | y ) ) {
// First subset is okay to return unimplemented.
SkDebugf ( " [terminated] subset codec not supported \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
// If the first subset succeeded, why would a later one fail?
// fall through to failure
default :
SkDebugf ( " [terminated] subset codec failed to decode (%d, %d, %d, %d) "
" with dimensions (%d x %d) \t error %d \n " ,
x , y , decodeInfo . width ( ) , decodeInfo . height ( ) ,
W , H , result ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-02-17 00:14:23 +00:00
}
// translate by the scaled height.
top + = decodeInfo . height ( ) ;
}
// translate by the scaled width.
left + = decodeInfo . width ( ) ;
}
SkDebugf ( " [terminated] Success! \n " ) ;
break ;
}
2016-12-08 14:07:56 +00:00
case 4 : { //kAnimated_Mode
std : : vector < SkCodec : : FrameInfo > frameInfos = codec - > getFrameInfo ( ) ;
if ( frameInfos . size ( ) = = 0 ) {
SkDebugf ( " [terminated] Not an animated image \n " ) ;
break ;
}
for ( size_t i = 0 ; i < frameInfos . size ( ) ; i + + ) {
options . fFrameIndex = i ;
auto result = codec - > startIncrementalDecode ( decodeInfo , bitmap . getPixels ( ) ,
bitmap . rowBytes ( ) , & options ) ;
if ( SkCodec : : kSuccess ! = result ) {
SkDebugf ( " [terminated] failed to start incremental decode "
" in frame %d with error %d \n " , i , result ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-12-08 14:07:56 +00:00
}
result = codec - > incrementalDecode ( ) ;
if ( result = = SkCodec : : kIncompleteInput ) {
SkDebugf ( " okay \n " ) ;
// Frames beyond this one will not decode.
break ;
}
if ( result = = SkCodec : : kSuccess ) {
SkDebugf ( " okay - decoded frame %d \n " , i ) ;
} else {
SkDebugf ( " [terminated] incremental decode failed with "
" error %d \n " , result ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-12-08 14:07:56 +00:00
}
}
SkDebugf ( " [terminated] Success! \n " ) ;
break ;
}
2016-01-21 13:03:28 +00:00
default :
2016-02-17 00:14:23 +00:00
SkDebugf ( " [terminated] Mode not implemented yet \n " ) ;
2016-01-21 13:03:28 +00:00
}
dump_png ( bitmap ) ;
2016-01-13 20:57:57 +00:00
}
2017-01-06 13:26:56 +00:00
static void fuzz_skp ( sk_sp < SkData > bytes ) {
2016-01-21 13:03:28 +00:00
SkMemoryStream stream ( bytes ) ;
SkDebugf ( " Decoding \n " ) ;
2016-03-18 14:25:55 +00:00
sk_sp < SkPicture > pic ( SkPicture : : MakeFromStream ( & stream ) ) ;
2016-01-21 13:03:28 +00:00
if ( ! pic ) {
2016-02-01 16:23:50 +00:00
SkDebugf ( " [terminated] Couldn't decode as a picture. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-01-21 13:03:28 +00:00
}
SkDebugf ( " Rendering \n " ) ;
SkBitmap bitmap ;
if ( ! FLAGS_dump . isEmpty ( ) ) {
SkIRect size = pic - > cullRect ( ) . roundOut ( ) ;
bitmap . allocN32Pixels ( size . width ( ) , size . height ( ) ) ;
}
SkCanvas canvas ( bitmap ) ;
canvas . drawPicture ( pic ) ;
2016-02-01 16:23:50 +00:00
SkDebugf ( " [terminated] Success! Decoded and rendered an SkPicture! \n " ) ;
2016-01-21 13:03:28 +00:00
dump_png ( bitmap ) ;
}
2016-01-13 20:57:57 +00:00
2017-01-06 13:26:56 +00:00
static void fuzz_icc ( sk_sp < SkData > bytes ) {
2016-10-24 13:24:02 +00:00
sk_sp < SkColorSpace > space ( SkColorSpace : : MakeICC ( bytes - > data ( ) , bytes - > size ( ) ) ) ;
2016-06-09 14:15:12 +00:00
if ( ! space ) {
SkDebugf ( " [terminated] Couldn't decode ICC. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-06-09 14:15:12 +00:00
}
SkDebugf ( " [terminated] Success! Decoded ICC. \n " ) ;
}
2017-01-06 13:26:56 +00:00
static void fuzz_color_deserialize ( sk_sp < SkData > bytes ) {
2016-06-23 17:49:27 +00:00
sk_sp < SkColorSpace > space ( SkColorSpace : : Deserialize ( bytes - > data ( ) , bytes - > size ( ) ) ) ;
if ( ! space ) {
SkDebugf ( " [terminated] Couldn't deserialize Colorspace. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-06-23 17:49:27 +00:00
}
SkDebugf ( " [terminated] Success! deserialized Colorspace. \n " ) ;
}
2017-01-06 18:48:19 +00:00
static void fuzz_path_deserialize ( sk_sp < SkData > bytes ) {
SkPath path ;
if ( ! path . readFromMemory ( bytes - > data ( ) , bytes - > size ( ) ) ) {
SkDebugf ( " [terminated] Couldn't initialize SkPath. \n " ) ;
return ;
}
SkDebugf ( " [terminated] Success! Initialized SkPath. \n " ) ;
}
2016-11-11 20:16:46 +00:00
# if SK_SUPPORT_GPU
2017-01-06 13:26:56 +00:00
static void fuzz_sksl2glsl ( sk_sp < SkData > bytes ) {
2016-10-18 17:06:24 +00:00
SkSL : : Compiler compiler ;
2016-11-21 15:39:35 +00:00
SkString output ;
2016-12-12 20:33:30 +00:00
SkSL : : Program : : Settings settings ;
sk_sp < GrShaderCaps > caps = SkSL : : ShaderCapsFactory : : Default ( ) ;
settings . fCaps = caps . get ( ) ;
std : : unique_ptr < SkSL : : Program > program = compiler . convertProgram ( SkSL : : Program : : kFragment_Kind ,
SkString ( ( const char * ) bytes - > data ( ) ) ,
settings ) ;
if ( ! program | | ! compiler . toGLSL ( * program , & output ) ) {
2016-10-18 17:06:24 +00:00
SkDebugf ( " [terminated] Couldn't compile input. \n " ) ;
2017-01-06 13:26:56 +00:00
return ;
2016-10-18 17:06:24 +00:00
}
SkDebugf ( " [terminated] Success! Compiled input. \n " ) ;
}
2016-11-11 20:16:46 +00:00
# endif
2016-10-18 17:06:24 +00:00
2016-09-12 19:01:44 +00:00
Fuzz : : Fuzz ( sk_sp < SkData > bytes ) : fBytes ( bytes ) , fNextByte ( 0 ) { }
2016-01-14 12:59:42 +00:00
2016-11-01 19:01:12 +00:00
void Fuzz : : signalBug ( ) { SkDebugf ( " Signal bug \n " ) ; raise ( SIGSEGV ) ; }
2016-01-15 13:46:54 +00:00
2016-07-19 23:50:03 +00:00
size_t Fuzz : : size ( ) { return fBytes - > size ( ) ; }
2016-11-01 19:01:12 +00:00
bool Fuzz : : exhausted ( ) {
return fBytes - > size ( ) = = fNextByte ;
2016-02-18 14:27:38 +00:00
}