Skip to content

Commit

Permalink
Disallow writing smaller manifest into asset than allocated for
Browse files Browse the repository at this point in the history
For compliant validators, this would cause a hash mismatch (#68)
  • Loading branch information
cyraxx committed Aug 14, 2024
1 parent d83f207 commit 01d6fc3
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 15 deletions.
13 changes: 8 additions & 5 deletions src/asset/BMFF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class BMFF extends BaseAsset implements Asset {

public async ensureManifestSpace(length: number): Promise<void> {
// Nothing to do?
if (((this.getManifestStoreBox()?.payload as C2PAManifestBoxPayload)?.manifestContent.length ?? 0) >= length)
if (((this.getManifestStoreBox()?.payload as C2PAManifestBoxPayload)?.manifestContent.length ?? 0) === length)
return;

const parts: {
Expand Down Expand Up @@ -160,8 +160,8 @@ export class BMFF extends BaseAsset implements Asset {

public async writeManifestJUMBF(jumbf: Uint8Array): Promise<void> {
const box = this.getManifestStoreBox();
if (!box || (box.payload as C2PAManifestBoxPayload).manifestContent.length < jumbf.length)
throw new Error('Not enough space in asset file');
if (!box || (box.payload as C2PAManifestBoxPayload).manifestContent.length !== jumbf.length)
throw new Error('Wrong amount of space in asset');

box.fillManifestContent(this.data, jumbf);
}
Expand Down Expand Up @@ -656,13 +656,16 @@ class C2PABox extends FullBox<C2PABoxPayload> {
*/
public fillManifestContent(buf: Uint8Array, manifest: Uint8Array): void {
const payload = this.payload as C2PAManifestBoxPayload;
payload.manifestContent.fill(0);
payload.manifestContent.set(manifest);

const dataView = new DataView(buf.buffer, this.payloadOffset, this.payloadSize);
// Write purpose string
payload.purpose.split('').forEach((c, i) => dataView.setUint8(i, c.charCodeAt(0)));
// Write null terminator
dataView.setUint8(payload.purpose.length, 0);
// Write Merkle offset
dataView.setBigUint64(payload.purpose.length + 1, payload.merkleOffset);
buf.set(payload.manifestContent, this.payloadOffset + payload.purpose.length + 9);
// Write content
buf.set(manifest, this.payloadOffset + payload.purpose.length + 9);
}
}
1 change: 0 additions & 1 deletion src/asset/JPEG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ export class JPEG extends BaseAsset implements Asset {
}

public async writeManifestJUMBF(jumbf: Uint8Array): Promise<void> {
// For JPEG, the segments' payload length needs to match the JUMBF length exactly
if (this.getJUMBFLength(this.manifestSegments) !== jumbf.length)
throw new Error('Wrong amount of space in asset');

Expand Down
13 changes: 4 additions & 9 deletions src/asset/PNG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ export class PNG extends BaseAsset implements Asset {
}

public async ensureManifestSpace(length: number): Promise<void> {
// Existing manifest chunk is already large enough?
if (this.manifestChunkIndex !== undefined && this.chunks[this.manifestChunkIndex].payloadLength >= length)
// Nothing to do?
if (this.manifestChunkIndex !== undefined && this.chunks[this.manifestChunkIndex].payloadLength === length)
return;

// Ensure there is a manifest chunk in the list of chunks
Expand Down Expand Up @@ -156,20 +156,15 @@ export class PNG extends BaseAsset implements Asset {
public async writeManifestJUMBF(jumbf: Uint8Array): Promise<void> {
if (
this.manifestChunkIndex === undefined ||
this.chunks[this.manifestChunkIndex].payloadLength < jumbf.length
this.chunks[this.manifestChunkIndex].payloadLength !== jumbf.length
) {
throw new Error('Not enough space in asset file');
throw new Error('Wrong amount of space in asset');
}

const manifestChunk = this.chunks[this.manifestChunkIndex];
const dataBuffer = manifestChunk.getSubBuffer(this.data);
dataBuffer.set(jumbf);

// If the chunk is larger than the manifest, zero out the remainder
if (manifestChunk.payloadLength > jumbf.length) {
dataBuffer.fill(0, jumbf.length);
}

// Update CRC
manifestChunk.updateCRC(this.data);
new DataView(this.data.buffer, manifestChunk.offset).setUint32(manifestChunk.length - 4, manifestChunk.crc);
Expand Down

0 comments on commit 01d6fc3

Please sign in to comment.