@@ -302,54 +302,213 @@ static void initialize_buffers(uint8_t *src_a, uint8_t *src_b, size_t size)
302302
303303}
304304
305- START_TEST (test_wb_patch_and_diff )
305+ static uint8_t pattern_byte (uint32_t seed , size_t index )
306+ {
307+ uint32_t value = seed ^ (uint32_t )index ;
308+
309+ value *= 1664525U ;
310+ value += 1013904223U ;
311+ value ^= (uint32_t )(index >> 8 );
312+ value ^= (uint32_t )(index >> 16 );
313+
314+ if ((uint8_t )value == ESC ) {
315+ value ^= 0x55U ;
316+ }
317+ return (uint8_t )value ;
318+ }
319+
320+ static void fill_pattern (uint8_t * dst , size_t size , uint32_t seed )
321+ {
322+ size_t i ;
323+
324+ for (i = 0 ; i < size ; ++ i ) {
325+ dst [i ] = pattern_byte (seed , i );
326+ }
327+ }
328+
329+ static uint32_t run_roundtrip_case (const uint8_t * src_a , uint32_t size_a ,
330+ const uint8_t * src_b , uint32_t size_b , uint32_t patch_capacity )
306331{
307332 WB_DIFF_CTX diff_ctx ;
308333 WB_PATCH_CTX patch_ctx ;
309- uint8_t src_a [SRC_SIZE ];
310- uint8_t src_b [SRC_SIZE ];
311- uint8_t patch [PATCH_SIZE ];
312- uint8_t patched_dst [DST_SIZE ];
313- int ret ;
314- int i ;
334+ uint8_t * src_a_copy ;
335+ uint8_t * patch ;
336+ uint8_t * patched_dst ;
337+ uint8_t * new_patch ;
338+ uint8_t block [DELTA_BLOCK_SIZE ] = {0 };
315339 uint32_t p_written = 0 ;
340+ uint32_t dst_written = 0 ;
341+ int ret ;
316342
343+ src_a_copy = malloc (size_a );
344+ patch = malloc (patch_capacity );
345+ patched_dst = malloc (size_b );
346+ ck_assert_ptr_nonnull (src_a_copy );
347+ ck_assert_ptr_nonnull (patch );
348+ ck_assert_ptr_nonnull (patched_dst );
317349
318- initialize_buffers ( src_a , src_b , SRC_SIZE );
350+ memcpy ( src_a_copy , src_a , size_a );
319351
320- ret = wb_diff_init (& diff_ctx , src_a , SRC_SIZE , src_b , SRC_SIZE );
352+ ret = wb_diff_init (& diff_ctx , src_a_copy , size_a , ( uint8_t * ) src_b , size_b );
321353 ck_assert_int_eq (ret , 0 );
322354
323- /* Create the patch */
324- for (i = 0 ; i < SRC_SIZE ; i += DELTA_BLOCK_SIZE ) {
325- ret = wb_diff (& diff_ctx , patch + p_written , DELTA_BLOCK_SIZE );
326- ck_assert_int_ge (ret , 0 ); /* Should not be 0 until patch is over*/
327- if (ret == 0 )
355+ for (;;) {
356+ uint32_t remaining = patch_capacity - p_written ;
357+
358+ ck_assert_uint_ge (remaining , BLOCK_HDR_SIZE );
359+ ret = wb_diff (& diff_ctx , patch + p_written ,
360+ remaining > DELTA_BLOCK_SIZE ? DELTA_BLOCK_SIZE : remaining );
361+ ck_assert_int_ge (ret , 0 );
362+ if (ret == 0 ) {
363+ if (diff_ctx .off_b < size_b ) {
364+ patch_capacity += DELTA_BLOCK_SIZE ;
365+ new_patch = realloc (patch , patch_capacity );
366+ ck_assert_ptr_nonnull (new_patch );
367+ patch = new_patch ;
368+ continue ;
369+ }
328370 break ;
329- p_written += ret ;
371+ }
372+ p_written += (uint32_t )ret ;
373+ ck_assert_uint_le (p_written , patch_capacity );
330374 }
331- ck_assert_int_gt (p_written , 0 ); /* Should not be 0 */
332375
333- printf ("patch size: %u\n" , p_written );
334- ret = wb_patch_init (& patch_ctx , src_a , SRC_SIZE , patch , p_written );
376+ ck_assert_uint_eq (diff_ctx .off_b , size_b );
377+ ck_assert_uint_gt (p_written , 0 );
378+
379+ ret = wb_patch_init (& patch_ctx , src_a_copy , size_a , patch , p_written );
335380 ck_assert_int_eq (ret , 0 );
336381
337- /* Apply the patch */
338- for (i = 0 ; i < SRC_SIZE ;)
339- {
340- ret = wb_patch (& patch_ctx , patched_dst + i , DELTA_BLOCK_SIZE );
341- ck_assert_int_ge (ret , 0 ); /* Should not be 0 until patch is over*/
342- if (ret == 0 )
382+ for (;;) {
383+ ret = wb_patch (& patch_ctx , block , sizeof (block ));
384+ ck_assert_int_ge (ret , 0 );
385+ if (ret == 0 ) {
343386 break ;
344- i += ret ;
387+ }
388+ ck_assert_uint_le (dst_written + (uint32_t )ret , size_b );
389+ memcpy (patched_dst + dst_written , block , (uint32_t )ret );
390+ dst_written += (uint32_t )ret ;
345391 }
346- ck_assert_int_gt (i , 0 ); /* Should not be 0 */
347- ck_assert_int_eq (i , SRC_SIZE ); // The patched length should match the buffer size
348392
349- /* Verify that the patched destination matches src_b */
350- for (i = 0 ; i < SRC_SIZE ; ++ i ) {
351- ck_assert_uint_eq (patched_dst [i ], src_b [i ]);
352- }
393+ ck_assert_uint_eq (dst_written , size_b );
394+ ck_assert_int_eq (memcmp (patched_dst , src_b , size_b ), 0 );
395+
396+ free (patched_dst );
397+ free (patch );
398+ free (src_a_copy );
399+ return p_written ;
400+ }
401+
402+ START_TEST (test_wb_patch_and_diff )
403+ {
404+ uint8_t src_a [SRC_SIZE ];
405+ uint8_t src_b [SRC_SIZE ];
406+ uint32_t p_written = 0 ;
407+
408+ initialize_buffers (src_a , src_b , SRC_SIZE );
409+
410+ p_written = run_roundtrip_case (src_a , SRC_SIZE , src_b , SRC_SIZE , PATCH_SIZE );
411+ printf ("patch size: %u\n" , p_written );
412+ }
413+ END_TEST
414+
415+ START_TEST (test_wb_patch_and_diff_identical_images )
416+ {
417+ uint8_t src_a [SRC_SIZE ];
418+ uint32_t p_written ;
419+
420+ fill_pattern (src_a , sizeof (src_a ), 0x12345678U );
421+
422+ p_written = run_roundtrip_case (src_a , sizeof (src_a ), src_a , sizeof (src_a ),
423+ PATCH_SIZE );
424+ ck_assert_uint_lt (p_written , 64 );
425+ }
426+ END_TEST
427+
428+ START_TEST (test_wb_patch_and_diff_completely_different_images )
429+ {
430+ uint8_t src_a [SRC_SIZE ];
431+ uint8_t src_b [SRC_SIZE ];
432+
433+ fill_pattern (src_a , sizeof (src_a ), 0x11111111U );
434+ fill_pattern (src_b , sizeof (src_b ), 0x22222222U );
435+
436+ (void )run_roundtrip_case (src_a , sizeof (src_a ), src_b , sizeof (src_b ),
437+ sizeof (src_b ) + DELTA_BLOCK_SIZE );
438+ }
439+ END_TEST
440+
441+ START_TEST (test_wb_patch_and_diff_all_escape_images )
442+ {
443+ uint8_t src_a [SRC_SIZE ];
444+ uint8_t src_b [SRC_SIZE ];
445+
446+ memset (src_a , ESC , sizeof (src_a ));
447+ memset (src_b , ESC , sizeof (src_b ));
448+
449+ (void )run_roundtrip_case (src_a , sizeof (src_a ), src_b , sizeof (src_b ),
450+ PATCH_SIZE );
451+ }
452+ END_TEST
453+
454+ START_TEST (test_wb_patch_and_diff_multi_sector_images )
455+ {
456+ int sector_size_ret ;
457+ uint32_t size ;
458+ uint8_t * src_a ;
459+ uint8_t * src_b ;
460+
461+ sector_size_ret = wb_diff_get_sector_size ();
462+ ck_assert_int_gt (sector_size_ret , BLOCK_HDR_SIZE );
463+ size = (uint32_t )(3 * sector_size_ret + 37 );
464+
465+ src_a = malloc (size );
466+ src_b = malloc (size );
467+ ck_assert_ptr_nonnull (src_a );
468+ ck_assert_ptr_nonnull (src_b );
469+
470+ fill_pattern (src_a , size , 0xA5A5A5A5U );
471+ memcpy (src_b , src_a , size );
472+ src_b [sector_size_ret - 1 ] ^= 0x11 ;
473+ src_b [sector_size_ret ] ^= 0x22 ;
474+ src_b [(2 * sector_size_ret ) + 5 ] = ESC ;
475+
476+ (void )run_roundtrip_case (src_a , size , src_b , size , size + DELTA_BLOCK_SIZE );
477+
478+ free (src_b );
479+ free (src_a );
480+ }
481+ END_TEST
482+
483+ START_TEST (test_wb_patch_and_diff_size_changing_update )
484+ {
485+ uint8_t src_a [2048 ];
486+ uint8_t src_b [3077 ];
487+
488+ fill_pattern (src_a , sizeof (src_a ), 0x31415926U );
489+ fill_pattern (src_b , sizeof (src_b ), 0x27182818U );
490+ memcpy (src_b + 512 , src_a , sizeof (src_a ));
491+ src_b [0 ] = ESC ;
492+ src_b [sizeof (src_b ) - 1 ] ^= 0x5A ;
493+
494+ (void )run_roundtrip_case (src_a , sizeof (src_a ), src_b , sizeof (src_b ),
495+ sizeof (src_b ) + DELTA_BLOCK_SIZE );
496+ }
497+ END_TEST
498+
499+ START_TEST (test_wb_patch_and_diff_single_byte_difference )
500+ {
501+ uint8_t src_a [SRC_SIZE ];
502+ uint8_t src_b [SRC_SIZE ];
503+ uint32_t p_written ;
504+
505+ fill_pattern (src_a , sizeof (src_a ), 0x0BADB002U );
506+ memcpy (src_b , src_a , sizeof (src_a ));
507+ src_b [1537 ] ^= 0x01 ;
508+
509+ p_written = run_roundtrip_case (src_a , sizeof (src_a ), src_b , sizeof (src_b ),
510+ PATCH_SIZE );
511+ ck_assert_uint_lt (p_written , 64 );
353512}
354513END_TEST
355514
@@ -376,6 +535,12 @@ Suite *patch_diff_suite(void)
376535 tcase_add_test (tc_wolfboot_delta , test_wb_diff_preserves_main_loop_header_margin_for_escape );
377536 tcase_add_test (tc_wolfboot_delta , test_wb_diff_rejects_match_offsets_beyond_24_bits );
378537 tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff );
538+ tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff_identical_images );
539+ tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff_completely_different_images );
540+ tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff_all_escape_images );
541+ tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff_multi_sector_images );
542+ tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff_size_changing_update );
543+ tcase_add_test (tc_wolfboot_delta , test_wb_patch_and_diff_single_byte_difference );
379544 suite_add_tcase (s , tc_wolfboot_delta );
380545
381546 return s ;
0 commit comments