The Universal Binary of Crashiness

June 9th, 2008 by Joe Ranieri

What would you say to an application that crashes Finder to the point of being useless? One that merely has to be downloaded, and not even run? I present NukeApp.

For those who don’t feel like experiencing this firsthand, the behavior will vary depending on your Safari download settings. If you’ve set it automatically open downloaded files, Safari will crash and the world will be happy. If you have that option turned off, and you open the zip file up in Finder, Finder will enter a crash loop.

View a movie of the experience.


So, on to the technical details. I’ll start off by saying that this binary has been specifically crafted and is not a valid universal binary — it lies horribly about the number of architectures it contains.

Let’s take a look at the stack trace for where it dies (only showing the top few frames):

_LSAddExecutableFormatInfo
_LSAddBundleExecutableInfo
_LSRegisterDirectoryNode
_LSFindOrRegisterBundleNode
_LSCopyInfoForNode
_LSCopyItemInfoForRefInfo

Aha, it’s LaunchServices giving us the trouble! It looks like Finder is asking it for information about the application and LaunchServices is registering the application in its database. From the looks of it, it’s trying to determine the format of the executable. A closer look at the top function reveals that it’s opening the file and reading it in:

movl        0xfffffb08(%ebp),%eax
leal        0xfffffd34(%ebp),%edx
movl        $0x00000200,0x08(%esp)
movl        %edx,0xfffffafc(%ebp)
movl        %edx,0x04(%esp)
movl        %eax,(%esp)
calll       read$UNIX2003

You’ll notice it’s only reading 512 (0×200) bytes. A bit after this it checks the first long in the data to see which type of executable it is - Mach-O, Mach-O 64-bit, PEF, or a fat binary. If we go down the function a bit more, you’ll notice there’s some strings for each arch type (ppc, ppc64, i386, x86_64). So, what it must be doing is looping through each fat_arch that follows the fat_header. However, since we’re getting crashes, it must not be making sure that it stops reading at the end of its buffer.

Here’s an example that suffers the same issue (ignoring endian issues):

int file = open("/path/to/binary")
char buffer[512];
 
read(buffer, sizeof(buffer), file);
 
fat_header *header = buffer;
fat_arch *archs = buffer + sizeof(fat_header);
 
for(int i = 0; i < header->nfat_archs; i++) {
	// do something with archs[i]
}

This situation comes up in a few diferent places… so how do they handle it?:

  • CFBundle restricts nfat_archs count to the most that fits in the buffer
  • the kernel loader returns error if the archs exceed the size of its buffer (one page size)

I’ll also note that this is not exploitable (it ONLY reads 512 bytes into a 512 byte buffer) and occurs in every version of OS X we could lay our hands on (10.4, 10.5, etc). You cannot inject code into Finder, the Dock, or any other process that crashes in this routine. It’s simply a crash.

We reported this to Apple February 28th (radar 5771210), and have received no response.


Post updated June 9th, with video and slightly better explanation.


Boot Camp Drivers from OS X

January 17th, 2008 by Ryan Govostes

Windows and I don’t have a very friendly relationship. Over the course of a year, I might reinstall my copy of Windows XP SP 2 half a dozen times because, inevitably, some .dll, .sys, or .act file has managed to ruin it for everyone by going and getting corrupted. This has happened so many times that I now have to call Microsoft every time I want to activate Windows (twice for each install, since I also use VMWare) and listen to a bot read off a thousand-digit number in groups of five.

The most recent argument between Windows and me happened on Tuesday; an annoying freeze led to a nightmarish six hour battle. Sadly, Windows emerged the victor by dying completely and thoroughly. Time for a reinstall, which means tracking down all of the .dll, .sys, and .act files that I need…

As you may know, Boot Camp comes with drivers to increase compatibility with Apple hardware. During the betas, they were stored in a disk image inside the application bundle; in Leopard, the drivers are stored on the Leopard install DVD. The DVD is a hybrid disc, meaning it has partitions for both Windows and Mac OS X. By default, OS X will only mount the HFS+ partition (containing the installer), and Windows will only mount the ISO 9660 partition (containing the Boot Camp drivers).

So if you don’t have your install disc and no writable DVD-DL is within arm’s reach, is it possible to get OS X to mount the ISO 9660 partition from the ADC disk image and copy the drivers to a thumb drive? Indeed it is.

(As an aside, you can view the partition map of the disk image by running hdiutil pmap2 leopard_9a581_userdvd.dmg)

If we use hdiutil to attach the image as a block device, it’s possible to get the ISO 9660 part to mount by using the cd9660.util program.

$ hdiutil attach leopard_9a581_userdvd.dmg -nomount
expected   CRC32 $0108CBDC
/dev/disk3          	Apple_partition_scheme
/dev/disk3s1        	Apple_partition_map
/dev/disk3s2        	Apple_Driver_ATAPI
/dev/disk3s3        	Apple_HFS
$ mkdir /Volumes/Drivers
$ /System/Library/Filesystems/cd9660.fs/cd9660.util -m disk3 /Volumes/Drivers

And when you’re done:

$ umount /Volumes/Drivers
$ rm -Rf /Volumes/Drivers

That’s all for today. If you need me, I’ll be on the phone with Microsoft…


Mail.app: IMAP Folders not updating?

January 2nd, 2008 by Jonathan Johnson

Ever since switching to Leopard, Mail.app sometimes doesn’t update folders with new messages, even if the messages added to those folders are a result of rules in Mail.app. I searched, and found partial solutions to my liking, but here’s what I settled on.

In Script Editor, save this script somewhere:

on run
  tell application "System Events"
    if exists (application processes whose name is "Mail") then
      tell application "Mail"
        set everyIMAPAccount to every imap account
        repeat with eachIMAPAccount in everyIMAPAccount
          tell eachIMAPAccount
            synchronize with eachIMAPAccount
          end tell
        end repeat
      end tell
    end if
  end tell
end run

Next, add a new rule to Mail.app that has the condition “Any Message,” and the action “Run Applescript” using this AppleScript. All this script does is automatically run “Synchronize” on each account any time a new message is found. This ensures that all folders are kept up to date.

I’ve been using this solution for a week now, and it’s been a godsend.

Edit:

See comments for a much simpler script.


Objective-C 2.0 Property Encoding

December 4th, 2007 by Joe Ranieri

The only way to inspect an Objective C 2.0 property is with a call to property_getAttributes(); sadly, the data returned by this function is completely undocumented. Here’s what I figured out:

The data is simply a NULL terminated string. Inside this string are several parts, separated by commas. (I’m assuming the order doesn’t matter, but this could be incorrect.)

Misc:

  • R - the property is read-only
  • T<type> - the property’s type, where <type> is the result of @encode() of the property’s type.

Assignment modes:

  • C - the property is copied on assignment
  • & - the property is retained on assignment

References:

  • P - the property is a strong reference
  • W - the property is a weak reference

Property accessors:

  • D - the property is dynamic
  • G<getter> - the property’s getter (named <getter>)
  • S<setter> - the property’s setter (named <setter>)
  • V<ivar> - the property is synthesized, using the ivar <ivar>

CalendarKit gets URLs, bug fixes

November 19th, 2007 by Alacatia Labs, Inc.

We’re pleased to release a second update to CalendarKit to address the requests of some users. Version 1.2 adds a URL property to ALCalendarItem objects, and also corrects one bug regarding Task completion dates.

If you have purchased CalendarKit, your account page will give you the option of downloading the latest version. If you’re interested in learning more about CalendarKit and what it can bring to your applications, please visit http://alacatialabs.com/products/calendarkit/ and download a demo.

Our changes in this release were user-requested. We’re always willing to take your needs into consideration when planning new releases. Let us know if there’s anything we can do for you.


Am I drunk?

November 8th, 2007 by Ryan Govostes

A few weeks ago I wrote about a hidden preference pane that ships with Leopard, Archives.prefPane.

As an anonymous reader pointed out this afternoon, the post made an unexpected shift when I put up a screenshot of DiskImages.prefPane and continued to discuss it rather than Archives.prefPane. Apparently I was more than a little absent-minded — even the file name of the image is “archiveprefpane.png”!

I’ve corrected the old post, so I’ll leave you with the assurance that I’ll pay closer attention next time!


CalendarKit Adds Leopard iCal Support to REALbasic

November 7th, 2007 by Alacatia Labs, Inc.

Kyle, TX: CalendarKit provides an API for REALbasic-made applications to interact with a user’s calendars by providing fast, native integration with calendar software. It currently integrates with iCal 3 on Mac OS X 10.5 “Leopard,” and is the only supported way of manipulating .ics calendars on the new operating system.

A free demo of CalendarKit is available at:
http://alacatialabs.com/products/calendarkit

Licenses for CalendarKit cost $50 per developer, and source licenses are available.

About Alacatia Labs, Inc:
Alacatia Labs, Inc. was incorporated in the summer of 2007. We strive to operate it like a research facility rather than a monolithic corporation; in this sense, we seek to experiment and develop new technologies rather than make a buck. We’re enthusiastic about the work we do and are confident that this enthusiasm will show through our unique products.

For more information about Alacatia Labs, Inc, please visit:
http://www.alacatialabs.com/


Dock Extras

November 2nd, 2007 by Joe Ranieri

In 10.5, applications can update their dock icon even if they aren’t running, though the only known use of this is iCal. The way this works is that the Dock loads a piece of code (the Dock Extra) to draw the application’s icon for it.

Ok, so that’s not entirely accurate. The Dock tells SystemUIServer to load the Dock Extra and communicates via Mach IPC to get the icon. So, Dock Extras are NOT a way to load code into the Dock.

The Dock Extra bundle is found by the DockExtra key in the application’s Info.plist. As needed, SystemUIServer loads the Dock Extra bundle and creates an instance of its principal class.

As with manipulating the Dock icon in an actual application, you need to request it be redrawn yourself. To do this, you call getContext: to get the graphics context and the rect to draw in. Once you are done drawing, simply flush the context and call setDockImageFromContext:.

It should be noted that the SystemUIServer does NOT unload the bundle when you drag the icon off the Dock (it simply calls invalidate). This causes problems if you try to delete your app, because the Dock Extra is still in use.

It should also be noted that Dock Extras are only invoked when the application is visible on the Dock. It isn’t invoked when showing stacks or if there’s an alias to the application on the Dock.

Download DockExtras Example


Darwin 9 Source Code Available

October 31st, 2007 by Joe Ranieri

The source code for Darwin 9 (Leopard’s core) was made available this morning. Note that not all packages are up yet, including the Objective-C runtime and CoreFoundation.

Darwin 9 source code


iCal’s Abominable Stripes

October 29th, 2007 by Jonathan Johnson

For the most part, I like Leopard’s new look. Once upgraded to the GM release, the new dock style shocked me, but now it looks and feels great.

One bug report I filed with Apple didn’t get changed for the final release. iCal uses vertical stripes. Check it out:

It just looks awkward and out of place. I expect that one of these days the report will be closed as “Behaves as Designed.”

It’s sad: that’s how my report about the abominable PDF pop-down push-button in the print dialogs was treated. UI Inconsistencies annoy me :)