OK, I think I have something.
The bug seems to happen when the filename is not a multiple of 4 bytes. Upload makes multiple calls to recv_ptp_data, to get the filename length, the filename, and then the data (possibly in multiple calls if it is bigger than the buffer)
It appears that if one call to recv_ptp_data doesn't end on a 4 byte boundary, the next call is (sometimes ?) messed up somehow. What exactly happens isn't entirely clear, but padding the filename with \0s until it is 4 byte aligned appears to resolve the problem. This can be done entirely on the client, since the file calls on the camera end will just ignore the nulls.
An alternate approach would be to read the filename + data up to buf_size data all at, and then parse out the filename etc.
For a complete solution (assuming above is correct) we should also ensure that buffer_size is always divisible by 4, since various do multiple reads in buf_size chunks.
I haven't noticed any problems if the final call to recv_ptp_data reads a non-divisble by 4 size.
edit:
attached a patch against the ptpcam in chdkde which implements these changes. I have actually only tested using chdkptp, but the upload code is identical.
edit:
also included in chdkptp changeset 71
http://trac.assembla.com/chdkptp/changeset/71