Flawfinder version 2.0.10, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 223 Examining data/lighter-1.1.2/ErrorCorrection.h Examining data/lighter-1.1.2/File.h Examining data/lighter-1.1.2/GetKmers.cpp Examining data/lighter-1.1.2/GetKmers.h Examining data/lighter-1.1.2/Reads.h Examining data/lighter-1.1.2/Store.h Examining data/lighter-1.1.2/bloom_filter.hpp Examining data/lighter-1.1.2/old_bloom_filter.hpp Examining data/lighter-1.1.2/utils.h Examining data/lighter-1.1.2/KmerCode.h Examining data/lighter-1.1.2/ErrorCorrection.cpp Examining data/lighter-1.1.2/main.cpp FINAL RESULTS: data/lighter-1.1.2/File.h:52:4: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). strcpy( modeBuffer, mode ) ; data/lighter-1.1.2/File.h:133:3: [4] (format) vsprintf: Potential format string problem (CWE-134). Make format string constant. vsprintf( buffer, fmt, args ) ; data/lighter-1.1.2/Reads.h:65:5: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). strcpy( out, in + j + 1 ) ; data/lighter-1.1.2/Reads.h:70:5: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). strcpy( out, in + j + 1 ) ; data/lighter-1.1.2/Reads.h:141:6: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. sprintf( buffer, "%s/%s.cor.fq.gz", outputDirectory, fileName ) ; data/lighter-1.1.2/Reads.h:143:6: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. sprintf( buffer, "%s/%s.cor.fa.gz", outputDirectory, fileName ) ; data/lighter-1.1.2/Reads.h:148:6: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. sprintf( buffer, "%s/%s.cor.fq", outputDirectory, fileName ) ; data/lighter-1.1.2/Reads.h:150:6: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. sprintf( buffer, "%s/%s.cor.fa", outputDirectory, fileName ) ; data/lighter-1.1.2/Reads.h:160:4: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). strcpy( outputDirectory, d ) ; data/lighter-1.1.2/main.cpp:536:3: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. sprintf( buffer, "Finish loading trusted kmers from file %s.", loadTrustedKmers ) ; data/lighter-1.1.2/main.cpp:710:3: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. sprintf( buffer, "The trusted kmers are saved in file %s.", saveTrustedKmers ) ; data/lighter-1.1.2/bloom_filter.hpp:698:10: [3] (random) srand: This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). Use a more secure technique for acquiring random values. srand(static_cast<unsigned int>(random_seed_)); data/lighter-1.1.2/main.cpp:543:2: [3] (random) srand: This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). Use a more secure technique for acquiring random values. srand( 17 ) ; data/lighter-1.1.2/old_bloom_filter.hpp:569:10: [3] (random) srand: This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). Use a more secure technique for acquiring random values. srand(static_cast<unsigned int>(random_seed_)); data/lighter-1.1.2/ErrorCorrection.cpp:6:15: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. extern signed char nucToNum[26] ; data/lighter-1.1.2/ErrorCorrection.cpp:7:8: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. extern char numToNuc[26] ; data/lighter-1.1.2/File.h:51:4: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char modeBuffer[5] ; data/lighter-1.1.2/File.h:82:9: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). fp = fopen( fileName, mode ) ; data/lighter-1.1.2/File.h:130:3: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer[1024] ; data/lighter-1.1.2/GetKmers.h:23:2: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char tag[ MAX_READ_LENGTH / 8 ] ; data/lighter-1.1.2/KmerCode.h:7:15: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. extern signed char nucToNum[26] ; data/lighter-1.1.2/KmerCode.h:8:8: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. extern char numToNuc[26] ; data/lighter-1.1.2/Reads.h:15:2: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char id[MAX_ID_LENGTH] ; data/lighter-1.1.2/Reads.h:16:2: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char seq[MAX_READ_LENGTH] ; data/lighter-1.1.2/Reads.h:17:2: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char qual[MAX_READ_LENGTH] ; data/lighter-1.1.2/Reads.h:32:3: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char outputDirectory[256] ; data/lighter-1.1.2/Reads.h:75:3: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char id[MAX_ID_LENGTH] ; data/lighter-1.1.2/Reads.h:76:3: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char seq[MAX_READ_LENGTH] ; data/lighter-1.1.2/Reads.h:77:3: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char qual[MAX_READ_LENGTH] ; data/lighter-1.1.2/Reads.h:82:4: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( outputDirectory, "./" ) ; data/lighter-1.1.2/Reads.h:112:4: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer[1024], fileName[1024] ; data/lighter-1.1.2/Reads.h:183:4: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer[2048] ; data/lighter-1.1.2/Reads.h:221:4: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer[2048] ; data/lighter-1.1.2/Reads.h:265:4: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char failReason[4] = "" ; data/lighter-1.1.2/Reads.h:267:5: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( failReason, " oc" ) ; data/lighter-1.1.2/Reads.h:269:5: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( failReason, " ak" ) ; data/lighter-1.1.2/Reads.h:271:5: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( failReason, " lc" ) ; data/lighter-1.1.2/Reads.h:296:5: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer1[20] = "" ; data/lighter-1.1.2/Reads.h:297:5: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer2[20] = "" ; data/lighter-1.1.2/Reads.h:298:5: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer3[20] = "" ; data/lighter-1.1.2/Reads.h:312:6: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( buffer1, " cor" ) ; data/lighter-1.1.2/Reads.h:314:6: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer2, " bad_prefix=%d", badPrefix ) ; data/lighter-1.1.2/Reads.h:318:7: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer3, " trimmed=%d", badSuffix ) ; data/lighter-1.1.2/Reads.h:320:7: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer3, " bad_suffix=%d", badSuffix ) ; data/lighter-1.1.2/Reads.h:378:5: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char failReason[4] = "" ; data/lighter-1.1.2/Reads.h:380:6: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( failReason, " oc" ) ; data/lighter-1.1.2/Reads.h:382:6: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( failReason, " ak" ) ; data/lighter-1.1.2/Reads.h:384:6: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( failReason, " lc" ) ; data/lighter-1.1.2/Reads.h:407:6: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer1[20] = "" ; data/lighter-1.1.2/Reads.h:408:6: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer2[20] = "" ; data/lighter-1.1.2/Reads.h:409:6: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer3[20] = "" ; data/lighter-1.1.2/Reads.h:412:7: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. strcpy( buffer1, " cor" ) ; data/lighter-1.1.2/Reads.h:414:7: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer2, " bad_prefix=%d", badPrefix ) ; data/lighter-1.1.2/Reads.h:418:8: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer3, " trimmed=%d", badSuffix ) ; data/lighter-1.1.2/Reads.h:420:8: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer3, " bad_suffix=%d", badSuffix ) ; data/lighter-1.1.2/Store.h:215:14: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). FILE *fp = fopen( file, "w" ) ; data/lighter-1.1.2/Store.h:227:14: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). FILE *fp = fopen( file, "r" ) ; data/lighter-1.1.2/bloom_filter.hpp:39:23: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. static const unsigned char bit_mask[bits_per_char] = { data/lighter-1.1.2/main.cpp:23:8: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. signed char nucToNum[26] = { 0, -1, 1, -1, -1, -1, 2, data/lighter-1.1.2/main.cpp:28:1: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char numToNuc[26] = {'A', 'C', 'G', 'T'} ; data/lighter-1.1.2/main.cpp:202:2: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer[128] ; data/lighter-1.1.2/main.cpp:268:2: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. char buffer[1023] ; data/lighter-1.1.2/main.cpp:331:21: [2] (integer) atoi: Unless checked, the resulting number can exceed the expected range (CWE-190). If source untrusted, check both minimum and maximum, even if the input had no minus sign (large numbers can roll over into negative number; consider saving to an unsigned value if that is intended). MAX_CORRECTION = atoi( argv[i + 1] ) ; data/lighter-1.1.2/main.cpp:347:17: [2] (integer) atoi: Unless checked, the resulting number can exceed the expected range (CWE-190). If source untrusted, check both minimum and maximum, even if the input had no minus sign (large numbers can roll over into negative number; consider saving to an unsigned value if that is intended). kmerLength = atoi( argv[i + 1] ) ; data/lighter-1.1.2/main.cpp:366:17: [2] (integer) atoi: Unless checked, the resulting number can exceed the expected range (CWE-190). If source untrusted, check both minimum and maximum, even if the input had no minus sign (large numbers can roll over into negative number; consider saving to an unsigned value if that is intended). kmerLength = atoi( argv[i + 1] ) ; data/lighter-1.1.2/main.cpp:388:19: [2] (integer) atoi: Unless checked, the resulting number can exceed the expected range (CWE-190). If source untrusted, check both minimum and maximum, even if the input had no minus sign (large numbers can roll over into negative number; consider saving to an unsigned value if that is intended). numOfThreads = atoi( argv[i + 1] ) ; data/lighter-1.1.2/main.cpp:416:16: [2] (integer) atoi: Unless checked, the resulting number can exceed the expected range (CWE-190). If source untrusted, check both minimum and maximum, even if the input had no minus sign (large numbers can roll over into negative number; consider saving to an unsigned value if that is intended). zlibLevel = atoi( argv[i+1] ) ; data/lighter-1.1.2/main.cpp:478:3: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer, "Average coverage is %.3lf and alpha is %.3lf", 7.0 / alpha, alpha ) ; data/lighter-1.1.2/main.cpp:510:3: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer, "Bad quality threshold is \"%c\"", badQuality ) ; data/lighter-1.1.2/main.cpp:656:2: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer, "Bloom filter A's false positive rate: %lf", tableAFP ) ; data/lighter-1.1.2/main.cpp:665:4: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer, "The error rate is high. Lighter adjusts -maxcor to %d and bad quality threshold to \"%c\".", MAX_CORRECTION, badQuality ) ; data/lighter-1.1.2/main.cpp:668:4: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. sprintf( buffer, "The error rate is high. Lighter adjusts -maxcor to %d.", MAX_CORRECTION ) ; data/lighter-1.1.2/old_bloom_filter.hpp:35:23: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. static const unsigned char bit_mask[bits_per_char] = { data/lighter-1.1.2/ErrorCorrection.cpp:46:25: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int CreateAnchor( char *read, char *qual, int *fix, bool *storedKmer, KmerCode &kmerCode, Store *kmers ) data/lighter-1.1.2/ErrorCorrection.cpp:48:19: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). int readLength = strlen( read ) ; data/lighter-1.1.2/ErrorCorrection.cpp:48:27: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int readLength = strlen( read ) ; data/lighter-1.1.2/ErrorCorrection.cpp:77:24: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( numToNuc[j] == read[i] ) data/lighter-1.1.2/ErrorCorrection.cpp:79:13: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). char c = read[i] ; data/lighter-1.1.2/ErrorCorrection.cpp:80:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[i] = numToNuc[j] ; data/lighter-1.1.2/ErrorCorrection.cpp:98:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[k] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:106:5: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[i] = c ; data/lighter-1.1.2/ErrorCorrection.cpp:112:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[k] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:118:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[k] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:170:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[i] = c ; data/lighter-1.1.2/ErrorCorrection.cpp:196:28: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int ErrorCorrection( char *read, char *qual, KmerCode& kmerCode, int maxCorrection, char badQuality, Store *kmers, int &badPrefix, int &badSuffix, int &info ) data/lighter-1.1.2/ErrorCorrection.cpp:223:34: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( i = 0 ; i < kmerLength && read[i] ; ++i ) data/lighter-1.1.2/ErrorCorrection.cpp:225:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:235:11: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( ; read[i] ; ++i, ++kmerCnt ) data/lighter-1.1.2/ErrorCorrection.cpp:237:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:280:35: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). createAnchorPos = CreateAnchor( read, qual, fix, storedKmer, kmerCode, kmers ) ; data/lighter-1.1.2/ErrorCorrection.cpp:293:18: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). printf( "%s\n", read ) ; data/lighter-1.1.2/ErrorCorrection.cpp:366:14: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). backupC = read[ createAnchorPos ] ; data/lighter-1.1.2/ErrorCorrection.cpp:367:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[ createAnchorPos ] = numToNuc[ fix[ createAnchorPos ] ] ; data/lighter-1.1.2/ErrorCorrection.cpp:374:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:382:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:386:25: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( numToNuc[c] == read[i - 1] ) data/lighter-1.1.2/ErrorCorrection.cpp:389:25: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( numToNuc[c] == read[i - 1] ) data/lighter-1.1.2/ErrorCorrection.cpp:398:38: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( t = 0 ; t < kmerLength && read[i + t] ; ++t ) // and it is should be a very good fix data/lighter-1.1.2/ErrorCorrection.cpp:400:27: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). tmpKmerCode.Append( read[i + t] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:404:12: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( !read[i + t] || t >= kmerLength ) data/lighter-1.1.2/ErrorCorrection.cpp:413:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:425:24: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:429:27: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( numToNuc[c] == read[i - 1] ) data/lighter-1.1.2/ErrorCorrection.cpp:439:45: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( t = 0 ; t <= kmerLength / 2 && read[i + t] ; ++t ) // and it is should be a very good fix data/lighter-1.1.2/ErrorCorrection.cpp:441:29: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). tmpKmerCode.Append( read[i + t] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:462:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[ createAnchorPos ] = backupC ; data/lighter-1.1.2/ErrorCorrection.cpp:497:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[k] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:546:39: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( k == i + 1 && j == nucToNum[ read[i] - 'A' ] ) data/lighter-1.1.2/ErrorCorrection.cpp:552:52: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). else if ( k == i + 1 && maxChange == nucToNum[ read[i] - 'A' ] ) data/lighter-1.1.2/ErrorCorrection.cpp:630:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:650:14: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). backupC = read[ createAnchorPos ] ; data/lighter-1.1.2/ErrorCorrection.cpp:651:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[ createAnchorPos ] = numToNuc[ fix[ createAnchorPos ] ] ; data/lighter-1.1.2/ErrorCorrection.cpp:659:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:669:22: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:673:25: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( numToNuc[c] == read[tag + j] ) data/lighter-1.1.2/ErrorCorrection.cpp:684:28: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). tmpKmerCode.Prepend( read[tag + j - t - 1] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:698:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:710:24: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:714:27: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( numToNuc[c] == read[tag + j] ) data/lighter-1.1.2/ErrorCorrection.cpp:726:30: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). tmpKmerCode.Prepend( read[tag + j - t - 1] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:747:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[ createAnchorPos ] = backupC ; data/lighter-1.1.2/ErrorCorrection.cpp:780:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Prepend( read[k] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:818:39: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( k == i - 1 && j == nucToNum[ read[i] - 'A' ] ) data/lighter-1.1.2/ErrorCorrection.cpp:824:51: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). else if ( k == i -1 && minChange == nucToNum[ read[i] - 'A' ] ) data/lighter-1.1.2/ErrorCorrection.cpp:887:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/ErrorCorrection.cpp:965:71: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( i >= overCorrectWindow && ( fix[i - overCorrectWindow] >= 0 && read[i - overCorrectWindow] != 'N' ) ) data/lighter-1.1.2/ErrorCorrection.cpp:972:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( fix[i] >= 0 && read[i] != 'N' ) data/lighter-1.1.2/ErrorCorrection.cpp:1058:8: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( read[i] != numToNuc[ fix[i] ] ) data/lighter-1.1.2/ErrorCorrection.cpp:1060:4: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[i] = numToNuc[ fix[i] ] ; data/lighter-1.1.2/ErrorCorrection.cpp:1101:36: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int ErrorCorrection_Wrapper( char *read, char *qual, KmerCode& kmerCode, char badQuality, Store *kmers, int &badPrefix, int &badSuffix, int &info ) data/lighter-1.1.2/ErrorCorrection.cpp:1105:17: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). int len = (int)strlen( read ) ; data/lighter-1.1.2/ErrorCorrection.cpp:1105:25: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int len = (int)strlen( read ) ; data/lighter-1.1.2/ErrorCorrection.cpp:1109:32: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). correction = ErrorCorrection( read, qual, kmerCode, MAX_CORRECTION, badQuality, kmers, data/lighter-1.1.2/ErrorCorrection.cpp:1125:12: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). char c = read[badPrefix] ; data/lighter-1.1.2/ErrorCorrection.cpp:1126:3: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[ badPrefix ] = '\0' ; data/lighter-1.1.2/ErrorCorrection.cpp:1127:26: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). tmp = ErrorCorrection( read, qual, kmerCode, MAX_CORRECTION, badQuality, kmers, data/lighter-1.1.2/ErrorCorrection.cpp:1130:3: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[ badPrefix ] = c ; data/lighter-1.1.2/ErrorCorrection.cpp:1165:3: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[len - badSuffix] = '\0' ; data/lighter-1.1.2/ErrorCorrection.h:28:36: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int ErrorCorrection_Wrapper( char *read, char *qual, KmerCode& kmerCode, char badQuality, Store *kmers, int &badPrefix, int &badSuffix, int &info ) ; data/lighter-1.1.2/File.h:43:13: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). int len = strlen( fileName ) ; data/lighter-1.1.2/File.h:119:31: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). return gzwrite( gzFp, buf, strlen( buf ) ) ; data/lighter-1.1.2/File.h:136:34: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). return gzwrite( gzFp, buffer, strlen( buffer ) ) ; data/lighter-1.1.2/GetKmers.cpp:82:16: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). len = (int)strlen( read ) ; data/lighter-1.1.2/GetKmers.cpp:82:24: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). len = (int)strlen( read ) ; data/lighter-1.1.2/GetKmers.cpp:83:10: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( read[len - 1] == '\n' ) data/lighter-1.1.2/GetKmers.cpp:84:6: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[len - 1] = '\0' ; data/lighter-1.1.2/GetKmers.cpp:95:19: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( i = 0 ; read[i] ; ++i ) data/lighter-1.1.2/GetKmers.cpp:96:24: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). tag = tag * 7 + ( read[i] - 'A' ) ; data/lighter-1.1.2/GetKmers.cpp:115:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.cpp:125:13: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( ; read[i] ; ++i ) data/lighter-1.1.2/GetKmers.cpp:127:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.cpp:184:31: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). void SampleKmersInRead( char *read, char *qual, int kmerLength, double alpha, KmerCode &kmerCode, Store *kmers ) data/lighter-1.1.2/GetKmers.cpp:203:34: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( i = 0 ; i < kmerLength && read[i] ; ++i ) data/lighter-1.1.2/GetKmers.cpp:205:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.cpp:224:10: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( ; read[i] ; ++i ) data/lighter-1.1.2/GetKmers.cpp:226:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.cpp:274:19: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). int len = (int)strlen( read ) ; data/lighter-1.1.2/GetKmers.cpp:274:27: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). int len = (int)strlen( read ) ; data/lighter-1.1.2/GetKmers.cpp:275:9: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). if ( read[len - 1] == '\n' ) data/lighter-1.1.2/GetKmers.cpp:276:5: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). read[len - 1] = '\0' ; data/lighter-1.1.2/GetKmers.cpp:284:23: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). StoreTrustedKmers( read, qual, myArg->kmerLength, myArg->badQuality, myArg->threshold, data/lighter-1.1.2/GetKmers.cpp:295:31: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). void StoreTrustedKmers( char *read, char *qual, int kmerLength, char badQuality, int *threshold, data/lighter-1.1.2/GetKmers.cpp:305:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.cpp:312:10: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). for ( ; read[i] ; ++i ) data/lighter-1.1.2/GetKmers.cpp:314:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.cpp:407:20: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). kmerCode.Append( read[i] ) ; data/lighter-1.1.2/GetKmers.h:56:31: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). void SampleKmersInRead( char *read, char *qual, int kmerLength, double alpha, KmerCode &kmerCode, Store *kmers ) ; data/lighter-1.1.2/GetKmers.h:59:31: [1] (buffer) read: Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). void StoreTrustedKmers( char *read, char *qual, int kmerLength, char badQuality, int *threshold, data/lighter-1.1.2/Reads.h:39:19: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). int len = (int)strlen( in ) ; data/lighter-1.1.2/Reads.h:137:14: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). int len = strlen( file ) ; data/lighter-1.1.2/Reads.h:203:15: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). len = (int)strlen( id ) ; data/lighter-1.1.2/Reads.h:206:15: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). len = (int)strlen( seq ) ; data/lighter-1.1.2/Reads.h:246:16: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). len = (int)strlen( id ) ; data/lighter-1.1.2/Reads.h:249:16: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). len = (int)strlen( seq ) ; data/lighter-1.1.2/Reads.h:327:13: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). qual[ strlen( qual ) - badSuffix ] = '\0' ; data/lighter-1.1.2/Reads.h:427:14: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). qual[ strlen( qual ) - badSuffix ] = '\0' ; data/lighter-1.1.2/bloom_filter.hpp:266:18: [1] (buffer) equal: Function does not check the second iterator for over-read conditions (CWE-126). This function is often discouraged by most C++ coding standards in favor of its safer alternatives provided since C++14. Consider using a form of this function that checks the second iterator before potentially overflowing it. std::equal(f.bit_table_,f.bit_table_ + raw_table_size_,bit_table_); data/lighter-1.1.2/main.cpp:163:33: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). ++qualHisto[ (int)reads.qual[ strlen( reads.seq ) - 1 ] ] ; data/lighter-1.1.2/main.cpp:193:15: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). totalLen += strlen( reads.seq ) ; data/lighter-1.1.2/old_bloom_filter.hpp:232:18: [1] (buffer) equal: Function does not check the second iterator for over-read conditions (CWE-126). This function is often discouraged by most C++ coding standards in favor of its safer alternatives provided since C++14. Consider using a form of this function that checks the second iterator before potentially overflowing it. std::equal(f.bit_table_,f.bit_table_ + raw_table_size_,bit_table_); ANALYSIS SUMMARY: Hits = 180 Lines analyzed = 5371 in approximately 0.13 seconds (41232 lines/second) Physical Source Lines of Code (SLOC) = 4103 Hits@level = [0] 41 [1] 107 [2] 59 [3] 3 [4] 11 [5] 0 Hits@level+ = [0+] 221 [1+] 180 [2+] 73 [3+] 14 [4+] 11 [5+] 0 Hits/KSLOC@level+ = [0+] 53.863 [1+] 43.8703 [2+] 17.7919 [3+] 3.41214 [4+] 2.68097 [5+] 0 Dot directories skipped = 1 (--followdotdir overrides) Minimum risk level = 1 Not every hit is necessarily a security vulnerability. There may be other security vulnerabilities; review your code! See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information.