From 4eca6b7937e81b152645150fc94022773a69a468 Mon Sep 17 00:00:00 2001 From: Jesse Burt Date: Sun, 23 Feb 2025 18:51:40 -0500 Subject: [PATCH] math.crc.spin: - handle some edge cases in the internet checksum function a little better - rename the optional init checksum parameter and give it a default value of 0 --- library/math.crc.spin | 47 +++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/library/math.crc.spin b/library/math.crc.spin index be9d1e2..439b31c 100644 --- a/library/math.crc.spin +++ b/library/math.crc.spin @@ -4,7 +4,7 @@ Description: A collection of CRC and checksum routines Author: Jesse Burt Started: Nov 19, 2017 - Updated: Jan 31, 2025 + Updated: Feb 23, 2025 Copyright (c) 2025 - See end of file for terms of use. ---------------------------------------------------------------------------------------------------- } @@ -41,27 +41,40 @@ PUB checksum8_twos_comp(p_buff, len): c return ( ( $ff - c ) + 1 ) ' return two's complement of the sum -PUB inet_chksum(ptr_buff, len, pshdr_chk): cksum | i +PUB inet_chksum(p_buff, len, iv=0): ck | i ' Checksum used in various internet datagrams -' ptr_buff: pointer to buffer of data to calculate checksum -' len: length of data -' pshdr_chk: optional checksum to add to this checksum, e.g., the checksum of a -' UDP or TCP pseudo-header. Specify 0, if unused. - { checksum is word-oriented, so _always_ process two bytes at a time - An even number required for len is thus implied; if the length of data - is odd, pad the source data with a zero. } - cksum := 0 +' p_buff: pointer to buffer of data to calculate checksum +' len: length of data +' iv: optional initial value to add to this checksum, e.g., the checksum of a +' UDP or TCP pseudo-header. + ' handle edge cases; these shouldn't generally happen, but should offer basic protection + if ( len == 0 ) + return 0 + + if ( len == 1 ) + return !( (byte[p_buff][0] << 8) & $ffff) + ' + + ck := 0 + + ' Process two bytes at a time repeat i from 0 to (len-2) step 2 - cksum += (byte[ptr_buff][i] << 8) | byte[ptr_buff][i+1] + ck += (byte[p_buff][i] << 8) | byte[p_buff][i+1] + + ' Handle an odd-length buffer by padding with zero + if ( len & 1 ) + ck += byte[p_buff][len-1] << 8 + + ' Add the optional pseudo-header check + ck += iv - { isolate the total carried, add it to the checksum and return - the complement as the final result } - cksum := ( !(cksum + cksum.word[1]) ) & $ffff + ' Fold carry into lower 16 bits (repeated if needed) + repeat while (ck > $ffff) + ck := (ck & $ffff) + (ck >> 16) - { add the optional pseudo-header checksum to the result } - cksum += pshdr_chk - cksum.word[0] += cksum.word[1] + ' Return one's complement of the result + return !ck & $ffff PUB meas_crc8(data, len): crc | currbyte, i, j