2024-04-22 05:54 ftp://ftp.de.debian.org/debian/pool/main/s/sniffit/sniffit_0.5.orig.tar.gz cppcheck-options: --library=posix --library=gnu --library=bsd --inconclusive --enable=style,information --inline-suppr --template=daca2 --disable=missingInclude --suppress=unmatchedSuppression --check-library --debug-warnings --suppress=autoNoType --suppress=valueFlowBailout --suppress=bailoutUninitVar --suppress=symbolDatabaseWarning -D__GNUC__ --platform=unix64 -j1 platform: Linux-5.15.0-105-generic-x86_64-with-glibc2.35 python: 3.10.12 client-version: 1.3.56 compiler: g++ (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0 cppcheck: head 2.14.0 head-info: ea2e716 (2024-04-21 15:59:20 +0200) count: 117 117 elapsed-time: 11.4 11.0 head-timing-info: old-timing-info: head results: sniffit-sniffit-0.5/src/sn_analyse.c:8:1: error: syntax error: keyword 'if' is not allowed in global scope [syntaxError] sniffit-sniffit-0.5/src/sn_cfgfile.c:124:12: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable stderr [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sn_cfgfile.c:148:12: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable stderr [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sn_cfgfile.c:460:11: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable stderr [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sn_cfgfile.c:192:7: portability: Non reentrant function 'getservbyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getservbyname_r'. [prohibitedgetservbynameCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:216:7: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:226:25: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:231:10: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:234:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:238:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:240:26: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:248:32: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:255:40: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:256:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:265:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:269:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:271:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:279:32: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:286:40: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:287:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:296:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:301:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:304:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:314:14: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:325:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:328:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:340:10: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:343:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:347:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:349:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:357:31: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:364:40: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:365:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:374:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:378:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:380:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:388:31: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:395:40: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:396:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:405:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:410:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:413:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:423:14: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:433:27: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:436:19: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sn_cfgfile.c:50:6: error: Common realloc mistake: 'select_from_list' nulled but not freed upon failure [memleakOnRealloc] sniffit-sniffit-0.5/src/sn_cfgfile.c:70:6: error: Common realloc mistake: 'select_to_list' nulled but not freed upon failure [memleakOnRealloc] sniffit-sniffit-0.5/src/sn_cfgfile.c:89:6: error: Common realloc mistake: 'deselect_from_list' nulled but not freed upon failure [memleakOnRealloc] sniffit-sniffit-0.5/src/sn_cfgfile.c:109:6: error: Common realloc mistake: 'deselect_to_list' nulled but not freed upon failure [memleakOnRealloc] sniffit-sniffit-0.5/src/sn_cfgfile.c:166:25: style: Parameter 'host' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_cfgfile.c:169:16: style: Variable 'digit' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sn_cfgfile.c:179:30: style: Parameter 'servname' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_cfgfile.c:181:17: style: Variable 'ent' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sn_cfgfile.c:449:27: style: Parameter 'file' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_cfgfile.c:138:16: warning: Uninitialized variable: help [uninitvar] sniffit-sniffit-0.5/src/sn_cfgfile.c:129:10: note: Assuming condition is false sniffit-sniffit-0.5/src/sn_cfgfile.c:138:16: note: Uninitialized variable: help sniffit-sniffit-0.5/src/sn_cfgfile.c:162:16: warning: Uninitialized variable: help [uninitvar] sniffit-sniffit-0.5/src/sn_cfgfile.c:153:10: note: Assuming condition is false sniffit-sniffit-0.5/src/sn_cfgfile.c:162:16: note: Uninitialized variable: help sniffit-sniffit-0.5/src/sn_cfgfile.c:214:8: style: Unused variable: i [unusedVariable] sniffit-sniffit-0.5/src/sn_cfgfile.c:452:8: style: Unused variable: line_length [unusedVariable] sniffit-sniffit-0.5/src/sn_conn_desc.c:8:1: error: syntax error: keyword 'if' is not allowed in global scope [syntaxError] sniffit-sniffit-0.5/src/sn_logfile.c:96:18: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable S_IWUSR [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sn_logfile.c:41:27: style: Parameter 'logline' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:47:28: style: Parameter 'conn' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:47:40: style: Parameter 'user' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:54:27: style: Parameter 'conn' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:54:39: style: Parameter 'pass' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:61:25: style: Parameter 'conn' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:61:37: style: Parameter 'login' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:68:24: style: Parameter 'conn' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:68:36: style: Parameter 'msg' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:75:23: style: Parameter 'conn' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:75:35: style: Parameter 'pwd' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:82:24: style: Parameter 'conn' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_logfile.c:82:36: style: Parameter 'msg' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sn_packets.c:46:6: style: Unused variable: i [unusedVariable] sniffit-sniffit-0.5/src/sn_resolv.c:13:35: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable INADDR_NONE [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sn_resolv.c:19:18: style: Obsolescent function 'gethostbyname' called. It is recommended to use 'getaddrinfo' instead. [prohibitedgethostbynameCalled] sniffit-sniffit-0.5/src/sniffit.c:191:16: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable stderr [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sniffit.c:1091:41: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable _32_bit [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sniffit.c:1514:13: debug: valueFlowConditionExpressions bailout: Skipping function due to incomplete variable PCAP_ERRBUF_SIZE [valueFlowBailoutIncompleteVar] sniffit-sniffit-0.5/src/sniffit.c:1645:24: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sniffit.c:1648:28: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sniffit.c:1660:24: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sniffit.c:1663:28: portability: Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'. [prohibitedstrtokCalled] sniffit-sniffit-0.5/src/sniffit.c:1766:15: warning: Either the condition '(dev=malloc(strlen(forced_dev)+1))==NULL' is redundant or there is possible null pointer dereference: dev. [nullPointerRedundantCheck] sniffit-sniffit-0.5/src/sniffit.c:1764:44: note: Assuming that condition '(dev=malloc(strlen(forced_dev)+1))==NULL' is not redundant sniffit-sniffit-0.5/src/sniffit.c:1766:15: note: Null pointer dereference sniffit-sniffit-0.5/src/sniffit.c:1767:61: warning: Either the condition '(dev=malloc(strlen(forced_dev)+1))==NULL' is redundant or there is possible null pointer dereference: dev. [nullPointerRedundantCheck] sniffit-sniffit-0.5/src/sniffit.c:1764:44: note: Assuming that condition '(dev=malloc(strlen(forced_dev)+1))==NULL' is not redundant sniffit-sniffit-0.5/src/sniffit.c:1767:61: note: Null pointer dereference sniffit-sniffit-0.5/src/sniffit.c:678:9: style:inconclusive: Found duplicate branches for 'if' and 'else'. [duplicateBranch] sniffit-sniffit-0.5/src/sniffit.c:687:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:678:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:718:9: style:inconclusive: Found duplicate branches for 'if' and 'else'. [duplicateBranch] sniffit-sniffit-0.5/src/sniffit.c:727:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:718:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:971:9: style:inconclusive: Found duplicate branches for 'if' and 'else'. [duplicateBranch] sniffit-sniffit-0.5/src/sniffit.c:980:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:971:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:1008:9: style:inconclusive: Found duplicate branches for 'if' and 'else'. [duplicateBranch] sniffit-sniffit-0.5/src/sniffit.c:1017:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sniffit.c:1008:9: note: Found duplicate branches for 'if' and 'else'. sniffit-sniffit-0.5/src/sn_analyse.c:201:1: style: Consecutive return, break, continue, goto or throw statements are unnecessary. [duplicateBreak] sniffit-sniffit-0.5/src/sniffit.c:49:18: style: Parameter 'prog_name' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sniffit.c:207:18: style: Parameter 'file' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sniffit.c:284:21: style: Parameter 'file' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sniffit.c:325:21: style: Parameter 'file' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sniffit.c:358:12: style: Parameter 'data' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sniffit.c:413:13: style: Parameter 'data' can be declared as pointer to const [constParameterPointer] sniffit-sniffit-0.5/src/sniffit.c:445:18: style: Variable 'so' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:445:23: style: Variable 'dest' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:488:18: style: Variable 'so' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:488:23: style: Variable 'dest' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:498:18: style: Variable 'str_IP' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:1071:31: style: Parameter 'ipaddrpoint' can be declared as pointer to const. However it seems that 'packethandler' is a callback function, if 'ipaddrpoint' is declared with const you might also need to cast function pointer(s). [constParameterCallback] sniffit-sniffit-0.5/src/sniffit.c:1927:41: note: You might need to cast the function pointer here sniffit-sniffit-0.5/src/sniffit.c:1071:31: note: Parameter 'ipaddrpoint' can be declared as pointer to const sniffit-sniffit-0.5/src/sniffit.c:1639:27: style: Variable 'hlp2' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:1654:27: style: Variable 'hlp2' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sn_analyse.c:154:11: style: Variable 'p' can be declared as pointer to const [constVariablePointer] sniffit-sniffit-0.5/src/sniffit.c:775:35: error: Uninitialized struct member: tcphead.source [uninitStructMember] sniffit-sniffit-0.5/src/sniffit.c:777:35: error: Uninitialized struct member: tcphead.destination [uninitStructMember] sniffit-sniffit-0.5/src/sniffit.c:405:10: style: Unused variable: j [unusedVariable] sniffit-sniffit-0.5/src/sniffit.c:723:16: style: Variable 'prior' is assigned a value that is never used. [unreadVariable] sniffit-sniffit-0.5/src/sniffit.c:732:16: style: Variable 'prior' is assigned a value that is never used. [unreadVariable] sniffit-sniffit-0.5/src/sniffit.c:1013:16: style: Variable 'prior' is assigned a value that is never used. [unreadVariable] sniffit-sniffit-0.5/src/sniffit.c:1022:16: style: Variable 'prior' is assigned a value that is never used. [unreadVariable] sniffit-sniffit-0.5/src/sniffit.c:1081:17: style: Unused variable: datalen [unusedVariable] sniffit-sniffit-0.5/src/sniffit.c:1081:26: style: Unused variable: position [unusedVariable] sniffit-sniffit-0.5/src/sniffit.c:1513:30: style: Unused variable: buffer [unusedVariable] sniffit-sniffit-0.5/src/sniffit.c:1517:17: style: Unused variable: memsize [unusedVariable] sniffit-sniffit-0.5/src/sniffit.c:126:27: warning: Null pointer dereference: string [ctunullpointer] sniffit-sniffit-0.5/src/sn_cfgfile.c:227:18: note: Assuming that condition 'field!=NULL' is not redundant sniffit-sniffit-0.5/src/sn_cfgfile.c:338:20: note: Calling function strlower, 1st argument is null sniffit-sniffit-0.5/src/sniffit.c:126:27: note: Dereferencing argument string that is null diff: DONE