I've noticed a strange behavior in Rabbitsign-2.1. If an application's flash page ends at a location near the end of a page, by default, Rabbitsign automatically increases the page count by one, so that the signature can be saved. However, if the application is exactly n-page long (i.e. its size is exactly a multiple of 16384 bytes), Rabbitsign adds two pages instead of one.
For testing, I used this code snippet.
Code:
The assembler I used here is the GNU as, Z80 target. But it's only a detail and not important, all you should know is that it pads the program until the size is a multiple of 16384. Because our code is only one page long, it produces an output that is exactly 16384 bytes long.
Code:
Now it's the time to test Rabbitsign.
Code:
As you see, Rabbitsign attempts to add an extra page to hold the signature, but ultimately adds 2 pages and pads to 32769 bytes, instead of 1 page. If I remove 1-byte from the program, Rabbitsign produces an expected output.
Code:
Now Rabbitsign pads the program size to 16385 bytes / 2 pages, instead of 32769 bytes / 3 pages. After digging into the source, I discovered the code responsible for calculating the program size after padding, in app8x.c, line 96.
Code:
It appears to me that "((length + 0x4000) & ~0x3fff) + 1" is trying to, (1) Round the size to a multiple of 16384, (2) Add 1 byte to the size. So an extra page can be calculated. For example, ((16383 + 0x4000) & ~0x3fff) is rounded to 16384, adding one and we have 16385. However, ((16384 + 0x4000) & ~0x3fff) == 32768, adding one and we now have 32769 bytes - two, not one pages are padded. Perhaps I am wrong and it's actually a feature working as intended, but I think it's really strange and I suspect it's an off-by-one bug in the code, the constant 0x4000 used here should really be 0x3fff, i.e. (size + 0x3fff) & ~0x3fff + 1, so that 16384 rounds to 16384 and gets padded to 16385 bytes / two pages, not 32769 bytes / three pages.
The README says,
Code:
Is Rabbitsign still being maintained nowadays? Does it still accept bug reports and patches? Should I submit a patch to Benjamin Moody?
For testing, I used this code snippet.
Code:
; Master Field
.db 80h, 0Fh, 0, 0, 0, 0
; Name. Note that the name field reads 80 47 because the name specified here is 7 characters long.
.db 80h, 47h, "AppTest"
; Disable TI splash screen.
.db 80h, 90h
; Revision
.db 80h, 21h, 0
; Build
.db 80h, 31h, 1
; Pages
.db 80h, 81h, 0 ; dummy number to test rabbitsign
; Signing Key ID
.db 80h, 12h, 01, 0Fh
; Date stamp. Nothing ever checks this, so you can put nothing in it.
.db 03h, 22h, 09h, 00h
; Date stamp signature. Since nothing ever checks this, there's no
; reason ever to update it. Or even have data in it.
.db 02h, 00
; Final field
.db 80h, 70h
; There's no need for more padding here. TI just starts execution after
; the last field.
ASMStart:
.balign 16384
The assembler I used here is the GNU as, Z80 target. But it's only a detail and not important, all you should know is that it pads the program until the size is a multiple of 16384. Because our code is only one page long, it produces an output that is exactly 16384 bytes long.
Code:
$ ls -l data.bin
-rw-rw-r--. 1 gaizi gaizi 16384 Mar 29 07:58 data.bin
Now it's the time to test Rabbitsign.
Code:
$ rabbitsign -b data.bin -k 010F.key -o data.8ck -t 8xk -f -g
data.bin: warning: determined length: 16384
data.bin: warning: adding an extra page to hold app signature
data.bin: warning: application has an incorrect page count (actual: 3)
data.bin: warning: actual length: 32769
As you see, Rabbitsign attempts to add an extra page to hold the signature, but ultimately adds 2 pages and pads to 32769 bytes, instead of 1 page. If I remove 1-byte from the program, Rabbitsign produces an expected output.
Code:
$ dd if=data.bin of=data2.bin bs=1 count=16383
16383+0 records in
16383+0 records out
16383 bytes (16 kB, 16 KiB) copied, 0.0327535 s, 500 kB/s
$ mv data2.bin data.bin
$ rabbitsign -b data.bin -k 010F.key -o data.8ck -t 8xk -f -g
data.bin: warning: determined length: 16383
data.bin: warning: adding an extra page to hold app signature
data.bin: warning: application has an incorrect page count (actual: 2)
data.bin: warning: actual length: 16385
Now Rabbitsign pads the program size to 16385 bytes / 2 pages, instead of 32769 bytes / 3 pages. After digging into the source, I discovered the code responsible for calculating the program size after padding, in app8x.c, line 96.
Code:
/* If necessary, add an extra page to ensure that the signature
doesn't span a page boundary. */
if (((length + 69 + 0x3fff) >> 14) != ((length + 0x3fff) >> 14)) {
if (flags & (RS_ZEALOUSLY_PAD_APP | RS_IGNORE_ALL_WARNINGS)) {
rs_warning(NULL, app, "adding an extra page to hold app signature");
length = ((length + 0x4000) & ~0x3fff) + 1;
addedpage = 1;
}
It appears to me that "((length + 0x4000) & ~0x3fff) + 1" is trying to, (1) Round the size to a multiple of 16384, (2) Add 1 byte to the size. So an extra page can be calculated. For example, ((16383 + 0x4000) & ~0x3fff) is rounded to 16384, adding one and we have 16385. However, ((16384 + 0x4000) & ~0x3fff) == 32768, adding one and we now have 32769 bytes - two, not one pages are padded. Perhaps I am wrong and it's actually a feature working as intended, but I think it's really strange and I suspect it's an off-by-one bug in the code, the constant 0x4000 used here should really be 0x3fff, i.e. (size + 0x3fff) & ~0x3fff + 1, so that 16384 rounds to 16384 and gets padded to 16385 bytes / two pages, not 32769 bytes / three pages.
The README says,
Code:
Author
------
Benjamin Moody / floppusmaximus@users.sf.net
Bug reports, please.
Is Rabbitsign still being maintained nowadays? Does it still accept bug reports and patches? Should I submit a patch to Benjamin Moody?