// look for image-start markers more than 4 bytes into imageData. // if one is found, remove the portion of the handle before it and return true. // if none found, return false. bool scanForAnotherImageMarker( Handle imageData ) { UInt8 *packetStart, *dataStart, *dataEnd, *data; Size handleSize = GetHandleSize( imageData ); SInt32 offsetOfStart = -1L; packetStart = (UInt8*)imageData; dataStart = packetStart + 4; dataEnd = packetStart + handleSize; for( data = dataStart; data <= dataEnd-3; data++ ) { // JPEG SOI is FF D8, but it's always followed by another FF. if( ( 0xff == data[0] ) && ( 0xd8 == data[1] ) && ( 0xff == data[2] ) ) { offsetOfStart = data - packetStart; break; } // GIF start marker is 'GIF89a' etc. if ('G' == data[0] && 'I' == data[1] && 'F' == data[2] && '8' == data[3]) { offsetOfStart = data - packetStart; break; } } if( offsetOfStart > 0 ) { char mungerPleaseDelete; Munger( imageData, 0, nil, offsetOfStart, &mungerPleaseDelete, 0 ); return true; } else { return false; } }
static LONGINT Munger_invoker (Handle h, LONGINT offset, Ptr ptr1, LONGINT len1, Ptr ptr2, LONGINT len2, LONGINT *d0p) { LONGINT retval; LONGINT d0_var; retval = Munger (h, ptr1, len1, ptr2, len2); asm { move.l d0, d0_var } *d0p = d0_var; return retval; }
// Runs write munging tests on BitcodeRecords with the given Edits. It // then parses the written bitcode. ErrorMessages is the expected // error messages logged by the write munging, when no error recovery // is allowed. ErrorRecoveryMessages are messages, in addition to // ErrorMessages, when the writer applies error recovery. void CheckParseEdits(const uint64_t *Edits, size_t EditsSize, std::string ErrorMessages, std::string ErrorRecoveryMessages) { NaClParseBitcodeMunger Munger(ARRAY_TERM(BitcodeRecords)); EXPECT_FALSE(Munger.runTest(Edits, EditsSize, true)); std::string BadResults(ErrorMessages); BadResults.append(UnableToContinue); EXPECT_EQ(BadResults, Munger.getTestResults()); Munger.setTryToRecoverOnWrite(true); EXPECT_TRUE(Munger.runTest(Edits, EditsSize, true)); std::string GoodResults(ErrorMessages); GoodResults.append(ErrorRecoveryMessages); GoodResults.append("Successful parse!\n"); EXPECT_EQ(GoodResults, Munger.getTestResults()); }
// Show that writing out an illegal abbreviation index, causes the // parser to fail. TEST(MyNaClMungerWriteErrorTests, DieOnWriteBadAbbreviationIndex) { NaClWriteMunger Munger(ARRAY_TERM(BitcodeRecords)); Munger.setWriteBadAbbrevIndex(true); Munger.setRunAsDeathTest(true); EXPECT_DEATH( Munger.runTest(ARRAY(AbbrevIndex4VoidTypeEdit)), ".*" // Report problem while writing. "Error \\(Block 17\\)\\: Uses illegal abbreviation index\\: 4\\: \\[2\\]" ".*" // Corresponding error while parsing. "Fatal\\(35\\:0)\\: Invalid abbreviation \\# 4 defined for record" ".*" // Output of report_fatal_error. "LLVM ERROR\\: Unable to continue" ".*"); }
static void set_about_item(void){ Str255 aboutitem; StringHandle abouthandle; GetMenuItemText( GetMenuHandle(mApple), iAbout, aboutitem); abouthandle = NewString( aboutitem); if( abouthandle){ StringPtr curApName = LMGetCurApName(); long len = Munger( (Handle)abouthandle, 1, "MathLink\252", 9, curApName + 1, *curApName); if( len > 0){ **abouthandle = (unsigned char)len; HLock( (Handle)abouthandle); SetMenuItemText( GetMenuHandle(mApple), iAbout, *abouthandle); } DisposeHandle( (Handle)abouthandle); } }
// Show how we deal with additional abbreviations defined for a block, // once a bad abbreviation definition record is found. That is, we // remove all succeeding abbreviations definitions for that block. In // addition, any record refering to a remove abbreviation is changed // to use the default abbreviation. TEST(NaClMungedWriteErrorTests, TestRemovingAbbrevWithMultAbbrevs) { NaClWriteMunger Munger(ARRAY_TERM(BitcodeRecords)); const uint64_t FunctionEnterIndex = 7; const uint64_t Edits[] { FunctionEnterIndex, NaClMungedBitcode::Replace, // Set Abbrev bits = 3 1, naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 3, Terminator, RetVoidIndex, NaClMungedBitcode::AddBefore, // bad abbreviation! 2, naclbitc::BLK_CODE_DEFINE_ABBREV, 1, // 1, naclbitc::FUNC_CODE_INST_RET - 1, Terminator, RetVoidIndex, NaClMungedBitcode::AddBefore, // good abbreviation to ignore. 2, naclbitc::BLK_CODE_DEFINE_ABBREV, 1, 1, naclbitc::FUNC_CODE_INST_RET, Terminator, RetVoidIndex, NaClMungedBitcode::Replace, // reference to good abreviation. 5, naclbitc::FUNC_CODE_INST_RET, Terminator }; CheckDumpEdits( ARRAY(Edits), "Error (Block 12): Bad abbreviation operand encoding 9:" " 2: [65533, 1, 9]\n", "Error (Block 12): Ignoring abbreviation: 2: [65533, 1, 1, 10]\n" "Error (Block 12): Uses illegal abbreviation index: 5: [10]\n", " 0:0|<65532, 80, 69, 88, 69, 1, 0,|Magic Number: 'PEXE' (80, 69," " 88, 69)\n" " | 8, 0, 17, 0, 4, 0, 2, 0, 0, |PNaCl Version: 2\n" " | 0> |\n" " 16:0|1: <65535, 8, 2> |module { // BlockID = 8\n" " 24:0| 1: <65535, 17, 3> | types { // BlockID = 17\n" " 32:0| 3: <1, 2> | count 2;\n" " 34:5| 3: <2> | @t0 = void;\n" " 36:4| 3: <21, 0, 0> | @t1 = void ();\n" " 39:7| 0: <65534> | }\n" " 44:0| 3: <8, 1, 0, 0, 0> | define external void @f0();\n" // Edit to change number of abbrev bits to 3. " 48:6| 1: <65535, 12, 3> | function void @f0() { \n" " | | // BlockID" " = 12\n" " 56:0| 3: <1, 1> | blocks 1;\n" " | | %b0:\n" " 58:5| 3: <10> | ret void;\n" " 60:4| 0: <65534> | }\n" " 64:0|0: <65534> |}\n"); }
// Same as CheckParseEdits, but also runs the bitcode dumper on the // written bitcode records. DumpedBitcode is the expected dumped // bitcode. void CheckDumpEdits(const uint64_t *Edits, size_t EditsSize, std::string ErrorMessages, std::string ErrorRecoveryMessages, std::string DumpedBitcode, bool RecoveredTestHasError=false) { NaClObjDumpMunger Munger(ARRAY_TERM(BitcodeRecords)); EXPECT_FALSE(Munger.runTest(Edits, EditsSize)); std::string BadResults(ErrorMessages); BadResults.append(UnableToContinue); EXPECT_EQ(BadResults, Munger.getTestResults()); Munger.setTryToRecoverOnWrite(true); if (RecoveredTestHasError) EXPECT_FALSE(Munger.runTest(Edits, EditsSize)); else EXPECT_TRUE(Munger.runTest(Edits, EditsSize)); std::string GoodResults(ErrorMessages); GoodResults.append(ErrorRecoveryMessages); GoodResults.append(DumpedBitcode); EXPECT_EQ(GoodResults, Munger.getTestResults()); // Verify that we can also parse the bitcode. CheckParseEdits(Edits, EditsSize, ErrorMessages, ErrorRecoveryMessages); }
// Show that no error occurs if we write out the maximum allowable // block abbreviation index bit limit. TEST(NaClMungerWriteErrorTests, CanWriteBlockWithMaxLimit) { // Replace initial block enter with maximum bit size. const uint64_t Edit[] = { 0, NaClMungedBitcode::Replace, 1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, naclbitc::MaxAbbrevWidth, Terminator }; NaClWriteMunger Munger(ARRAY_TERM(BitcodeRecords)); EXPECT_TRUE(Munger.runTest(ARRAY(Edit))); EXPECT_EQ( " 1: [65535, 8, 32]\n" // Max abbreviation bit limit (32). " 1: [65535, 17, 3]\n" " 3: [1, 2]\n" " 3: [2]\n" " 3: [21, 0, 0]\n" " 0: [65534]\n" " 3: [8, 1, 0, 0, 0]\n" " 1: [65535, 12, 2]\n" " 3: [1, 1]\n" " 3: [10]\n" " 0: [65534]\n" " 0: [65534]\n", Munger.getTestResults()); }
static OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath) { OSErr result; OSErr realResult; FSSpec tempSpec; CInfoPBRec pb; *fullPathLength = 0; *fullPath = nil; /* Default to noErr */ realResult = result = noErr; result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec); if ( result == noErr ) { if ( tempSpec.parID == fsRtParID ) { /* The object is a volume */ /* Add a colon to make it a full pathname */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; /* We're done */ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); *fullPathLength = tempSpec.name[0]; } else { /* The object isn't a volume */ /* Is the object a file or a directory? */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrDirID = tempSpec.parID; pb.dirInfo.ioFDirIndex = 0; result = PBGetCatInfoSync(&pb); // Allow file/directory name at end of path to not exist. realResult = result; if ( (result == noErr) || (result == fnfErr) ) { /* if the object is a directory, append a colon so full pathname ends with colon */ if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; } /* Put the object name in first */ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); *fullPathLength = tempSpec.name[0]; if ( result == noErr ) { /* Get the ancestor directory names */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrParID = tempSpec.parID; do /* loop until we have an error or find the root directory */ { pb.dirInfo.ioFDirIndex = -1; pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; result = PBGetCatInfoSync(&pb); if ( result == noErr ) { /* Append colon to directory name */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; /* Add directory name to beginning of fullPath */ (void) Munger(*fullPath, 0, nil, 0, &tempSpec.name[1], tempSpec.name[0]); *fullPathLength += tempSpec.name[0]; result = MemError(); } } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) ); } } } } if ( result == noErr ) { /* Return the length */ /// *fullPathLength = GetHandleSize(*fullPath); result = realResult; // return realResult in case it was fnfErr } else { /* Dispose of the handle and return nil and zero length */ if ( *fullPath != nil ) { DisposeHandle(*fullPath); } *fullPath = nil; *fullPathLength = 0; } return ( result ); }
// Show that we can dump the bitcode records TEST(NaClMungeWriteErrorTests, DumpBitcodeRecords) { NaClObjDumpMunger Munger(ARRAY_TERM(BitcodeRecords)); EXPECT_TRUE(Munger.runTest()); EXPECT_EQ(ExpectedDumpedBitcode, Munger.getTestResults()); }
static void QTDR_DrawFrame (short theTrackWidth, short theTrackHeight, long theNumSample, GWorldPtr theGWorld) { Handle myHandle = NULL; char myData[kPICTFileHeaderSize]; static PicHandle myPicture = NULL; static GWorldPtr myGWorld = NULL; static GraphicsImportComponent myImporter = NULL; Rect myRect; RGBColor myColor; ComponentResult myErr = noErr; MacSetRect(&myRect, 0, 0, theTrackWidth, theTrackHeight); if (myPicture == NULL) { myErr = NewGWorld(&myGWorld, kPixelDepth, &myRect, NULL, NULL, (GWorldFlags)0); if (myErr != noErr) goto bail; // read a picture from our resource file myPicture = GetPicture(kPictureID); if (myPicture == NULL) goto bail; // use Munger to prepend a 512-byte header onto the picture data; this converts the PICT // resource data into in-memory PICT file data (see Ice Floe 14 for an explanation of this) myHandle = (Handle)myPicture; Munger(myHandle, 0, NULL, 0, myData, kPICTFileHeaderSize); // get a graphics importer for the picture myErr = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypePicture, &myImporter); if (myErr != noErr) goto bail; // configure the graphics importer myErr = GraphicsImportSetGWorld(myImporter, myGWorld, NULL); if (myErr != noErr) goto bail; myErr = GraphicsImportSetDataHandle(myImporter, myHandle); if (myErr != noErr) goto bail; myErr = GraphicsImportSetBoundsRect(myImporter, &myRect); if (myErr != noErr) goto bail; // draw the picture into the source GWorld myErr = GraphicsImportDraw(myImporter); if (myErr != noErr) goto bail; } // set the blend amount (0 = fully transparent; 0xffff = fully opaque) myColor.red = (theNumSample - 1) * (0xffff / kNumVideoFrames - 1); myColor.green = (theNumSample - 1) * (0xffff / kNumVideoFrames - 1); myColor.blue = (theNumSample - 1) * (0xffff / kNumVideoFrames - 1); OpColor(&myColor); // blend the picture (in the source GWorld) into the empty rectangle (in the destination GWorld) CopyBits((BitMapPtr)*GetGWorldPixMap(myGWorld), (BitMapPtr)*GetGWorldPixMap(theGWorld), &myRect, &myRect, blend, NULL); if (theNumSample == kNumVideoFrames) goto bail; return; bail: if (myHandle != NULL) DisposeHandle(myHandle); if (myPicture != NULL) ReleaseResource((Handle)myPicture); if (myImporter != NULL) CloseComponent(myImporter); }
OSErr FSpPathFromLocation( FSSpec *spec, /* The location we want a path for. */ int *length, /* Length of the resulting path. */ Handle *fullPath) /* Handle to path. */ { OSErr err; FSSpec tempSpec; CInfoPBRec pb; *fullPath = NULL; /* * Make a copy of the input FSSpec that can be modified. */ BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); if (tempSpec.parID == fsRtParID) { /* * The object is a volume. Add a colon to make it a full * pathname. Allocate a handle for it and we are done. */ tempSpec.name[0] += 2; tempSpec.name[tempSpec.name[0] - 1] = ':'; tempSpec.name[tempSpec.name[0]] = '\0'; err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); } else { /* * The object isn't a volume. Is the object a file or a directory? */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrDirID = tempSpec.parID; pb.dirInfo.ioFDirIndex = 0; err = PBGetCatInfoSync(&pb); if ((err == noErr) || (err == fnfErr)) { /* * If the file doesn't currently exist we start over. If the * directory exists everything will work just fine. Otherwise we * will just fail later. If the object is a directory, append a * colon so full pathname ends with colon, but only if the name is * not empty. NavServices returns FSSpec's with the parent ID set, * but the name empty... */ if (err == fnfErr) { BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) { if (tempSpec.name[0] > 0) { tempSpec.name[0] += 1; tempSpec.name[tempSpec.name[0]] = ':'; } } /* * Create a new Handle for the object - make it a C string. */ tempSpec.name[0] += 1; tempSpec.name[tempSpec.name[0]] = '\0'; err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); if (err == noErr) { /* * Get the ancestor directory names - loop until we have an * error or find the root directory. */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrParID = tempSpec.parID; do { pb.dirInfo.ioFDirIndex = -1; pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; err = PBGetCatInfoSync(&pb); if (err == noErr) { /* * Append colon to directory name and add * directory name to beginning of fullPath. */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]); err = MemError(); } } while ( (err == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) ); } } } /* * On error Dispose the handle, set it to NULL & return the err. * Otherwise, set the length & return. */ if (err == noErr) { *length = GetHandleSize(*fullPath) - 1; } else { if ( *fullPath != NULL ) { DisposeHandle(*fullPath); } *fullPath = NULL; *length = 0; } return err; }
pascal OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath) { OSErr result; OSErr realResult; FSSpec tempSpec; CInfoPBRec pb; *fullPathLength = 0; *fullPath = NULL; // Default to noErr realResult = noErr; /* Make a copy of the input FSSpec that can be modified */ BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); if ( tempSpec.parID == fsRtParID ) { /* The object is a volume */ /* Add a colon to make it a full pathname */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; /* We are done */ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); } else { /* The object is NOT a volume */ /* Is the object a file or a directory? */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrDirID = tempSpec.parID; pb.dirInfo.ioFDirIndex = 0; result = PBGetCatInfoSync(&pb); /* Allow file/directory name at end of path to not exist. */ realResult = result; if ( (result == noErr) || (result == fnfErr) ) { /* if the object is a directory, append a colon so full pathname ends with colon */ if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) { ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; } /* Put the object name in first */ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); if ( result == noErr ) { /* Get the ancestor directory names */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrParID = tempSpec.parID; do /* loop until we have an error or find the root directory */ { pb.dirInfo.ioFDirIndex = -1; pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; result = PBGetCatInfoSync(&pb); if ( result == noErr ) { /* Append colon to directory name */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; /* Add directory name to beginning of fullPath */ (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]); result = MemError(); } } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) ); } } } if ( result == noErr ) { /* Return the length */ *fullPathLength = InlineGetHandleSize(*fullPath); result = realResult; // return realResult in case it was fnfErr } else { /* Dispose of the handle and return NULL and zero length */ if ( *fullPath != NULL ) { DisposeHandle(*fullPath); } *fullPath = NULL; *fullPathLength = 0; } return ( result ); }