Lemon: Update code and remove cruft

Remove some unused historical files.

Aggressively disable warnings to keep the lemon source
pristine and avoid the maintenance burden for lemon itself.

Lemon has its own lax policy for warnings that doesn't match our
own and they won't accept external patches to remove the
warnings, so just ignore them. Lemon is just executed to generate
code for the Wireshark build and the minor code issues it has
have no influence at runtime.

For lemon generated code we selectively disable some linting
warnings.

Remove patches for lemon and lempar, they are no longer required
with these changes to silence warnings.
This commit is contained in:
João Valverde 2022-12-30 10:36:03 +00:00
parent 67a788b29c
commit f2218ae5f0
17 changed files with 145 additions and 476 deletions

View File

@ -39,9 +39,6 @@ gboolean has_wpcap = FALSE;
#include <wsutil/file_util.h>
#include <wsutil/ws_assert.h>
/* XXX - yes, I know, I should move cppmagic.h to a generic location. */
#include "tools/lemon/cppmagic.h"
#define MAX_WIN_IF_NAME_LEN 511
static void (*p_pcap_close) (pcap_t *);
@ -120,7 +117,7 @@ typedef struct {
gboolean optional;
} symbol_table_t;
#define SYM(x, y) { G_STRINGIFY(x) , (gpointer) &CONCAT(p_,x), y }
#define SYM(x, y) { G_STRINGIFY(x) , (gpointer) &G_PASTE(p_,x), y }
void
load_wpcap(void)

View File

@ -25,5 +25,12 @@ MACRO(ADD_LEMON_FILES _source _generated)
LIST(APPEND ${_source} ${_in})
LIST(APPEND ${_generated} ${_out}.c)
ENDFOREACH (_current_FILE)
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
set_source_files_properties(${_out}.c PROPERTIES COMPILE_OPTIONS "/w")
elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
set_source_files_properties(${_out}.c PROPERTIES COMPILE_OPTIONS "-Wno-unused-parameter")
else()
# Build with some warnings for lemon generated code
endif()
ENDFOREACH (_current_FILE)
ENDMACRO(ADD_LEMON_FILES)

View File

@ -101,9 +101,6 @@ CHECKAPI(
SWITCHES
SOURCES
${DFILTER_NONGENERATED_FILES}
# LEX files commented out due to use of malloc, free etc.
# ${LEX_FILES}
${LEMON_FILES}
)
#

View File

@ -14,58 +14,23 @@ if(DEFINED LEMON_C_COMPILER)
set(CMAKE_C_FLAGS "")
endif()
# To keep lemon.c as close to upstream as possible, deliberately ignore
# some stylistic issues.
set(lemon_cflags)
# To keep lemon.c as close to upstream as possible disable all warnings
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
# Normal MSVC has no warnings, but VS Code Analysis finds a bunch
# (when ENABLE_CODE_ANALYSIS is set).
set(lemon_cflags
/wd6001 # Using uninitialized memory '*zBuf'.
/wd6011 # Dereferencing NULL pointer 'cp'.
/wd6308 # realloc may return NULL and leak original memory.
/wd6385 # Buffer overrun (read) in Parse, related to 'cp'
/wd6386 # Buffer overrun (write) in Parse, related to 'filebuf'
/wd6387 # strlen(argv[0]) could receive a NULL pointer.
/wd28182 # Dereferencing NULL pointer. 'ap2' contains the same NULL value as 'ap' did.
/wd28183 # passing 0 (from realloc) to memcpy
/wd28199 # Using possibly uninitialized memory
)
target_compile_options(lemon PRIVATE /w)
else()
set(lemon_cflags_test
# GCC 8.2.1 is not smart enough to recognize "Fall thru ..."
-Wimplicit-fallthrough
-Wsign-compare
-Wunused-parameter
-Wshorten-64-to-32
# From WIRESHARK_C_ONLY_FLAGS
-Wc++-compat
-Wold-style-definition
-Wstrict-prototypes
)
if(ENABLE_EXTRA_COMPILER_WARNINGS)
list(APPEND lemon_cflags_test
-Wpedantic
-Wstrict-overflow
-Wcast-qual
-Wredundant-decls
-Wmissing-prototypes
-Wmissing-declarations
-Wcast-align
)
endif()
foreach(THIS_FLAG IN LISTS lemon_cflags_test)
string(MAKE_C_IDENTIFIER "C${THIS_FLAG}_VALID" _flag_var)
check_c_compiler_flag(${THIS_FLAG} ${_flag_var})
if(${_flag_var})
# Look for -Wfoo flags above in case it is cached, but
# actually disable the warning here with -Wno-foo.
string(REPLACE "-W" "-Wno-" THIS_FLAG "${THIS_FLAG}")
list(APPEND lemon_cflags ${THIS_FLAG})
endif()
endforeach()
target_compile_options(lemon PRIVATE -w)
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
# Disable static analysis for lemon source code. These issues don't
# affect Wireshark at runtime.
target_compile_options(lemon PRIVATE -Xclang -analyzer-disable-all-checks)
endif()
if(DEFINED NO_SANITIZE_CFLAGS)
target_compile_options(lemon PRIVATE ${NO_SANITIZE_CFLAGS})
endif()
if(DEFINED NO_SANITIZE_LDFLAGS)
target_link_options(lemon PRIVATE ${NO_SANITIZE_LDFLAGS})
endif()
target_compile_options(lemon PRIVATE ${lemon_cflags})
#
# Editor modelines - https://www.wireshark.org/tools/modelines.html

View File

@ -7,11 +7,11 @@ Git mirror of the upstream Fossil repository: https://github.com/mackyle/sqlite
The lempar.c and lemon.c are taken from sqlite and are modified as little as
possible to make it easier to synchronize changes. Last updated at:
commit 273ee151217b04c640c1af148e36c518678c89fa
Author: mistachkin <mistachkin@noemail.net>
Date: Mon Sep 21 20:18:44 2020 +0000
commit a913f942cf6b32b85de6428fd542b39458df2a88
Author: D. Richard Hipp <drh@hwaci.com>
Date: Wed Dec 28 14:03:47 2022 +0000
Fix harmless compiler warning seen with MSVC.
Version 3.40.1
To check for changes (adjust "previous commit" accordingly):
@ -26,6 +26,13 @@ To create a Wireshark version (steps 1-3) and validate the result (steps 4-5):
4. Check for CSA warnings: clang-check -analyze lemon.c --
5. Build and run lemon: ninja epan/dfilter/grammar.c
To keep the lemon source as pristine as possible from upstream all warnings
when building lemon itself are disabled. Only patch the lemon source code as
a last resort.
Warnings for lemon generated code are few in practice with -Wall -Wextra. These
are preferably selectively disabled in the Wireshark build.
The patches to lemon to silence compiler warnings and static analysis reports
(for edge cases that cannot occur) are not proposed upstream because that
process is difficult. From <https://www.sqlite.org/copyright.html>:

View File

@ -6,9 +6,11 @@
sed -e 's/ \+$//' -i lemon.c lempar.c
# Other patches
for i in patches/*.patch; do
echo "Applying $i"
patch --silent -p1 -i "$i"
done
if [ -d "patches" ]; then
for i in patches/*.patch; do
echo "Applying $i"
patch --silent -p1 -i "$i"
done
fi
echo DONE

View File

@ -1,13 +0,0 @@
/** @file */
/**************************************** CPP definitions ***************/
/* CPP magic: Concatenate two strings or macros that resolve to strings.
* Use CONCAT(), not _CONCAT() */
#define _CONCAT(a,b) a ## b
#define CONCAT(a,b) _CONCAT(a,b)
/* CPP magic: Surround a string or a macro that resolves to a string with
* double quotes. */
#define _STRINGIFY(a) # a
#define STRINGIFY(a) _STRINGIFY(a)

View File

@ -48,7 +48,7 @@ extern int access(const char *path, int mode);
#define MAXRHS 1000
#endif
extern void memory_error(void);
extern void memory_error();
static int showPrecedenceConflict = 0;
static char *msort(char*,char**,int(*)(const char*,const char*));
@ -401,7 +401,7 @@ struct lemon {
struct symbol *errsym; /* The error symbol */
struct symbol *wildcard; /* Token that matches anything */
char *name; /* Name of the generated parser */
char *arg; /* Declaration of the 3th argument to parser */
char *arg; /* Declaration of the 3rd argument to parser */
char *ctx; /* Declaration of 2nd argument to constructor */
char *tokentype; /* Type of terminal symbols in the parser stack */
char *vartype; /* The default type of non-terminal symbols */
@ -430,6 +430,7 @@ struct lemon {
};
#define MemoryCheck(X) if((X)==0){ \
extern void memory_error(); \
memory_error(); \
}
@ -694,13 +695,11 @@ int acttab_insert(acttab *p, int makeItSafe){
fprintf(stderr,"malloc failed\n");
exit(1);
}
assert(oldAlloc < p->nActionAlloc); /* hint for CSA */
for(i=oldAlloc; i<p->nActionAlloc; i++){
p->aAction[i].lookahead = -1;
p->aAction[i].action = -1;
}
}
assert(p->aAction); /* Hint for CSA (for p->aAction[i] below) */
/* Scan the existing action table looking for an offset that is a
** duplicate of the current transaction set. Fall out of the loop
@ -918,8 +917,11 @@ void FindStates(struct lemon *lemp)
lemp->errorcnt++;
sp = lemp->startRule->lhs;
}
}else{
}else if( lemp->startRule ){
sp = lemp->startRule->lhs;
}else{
ErrorMsg(lemp->filename,0,"Internal error - no start rule\n");
exit(1);
}
/* Make sure the start symbol doesn't occur on the right-hand side of
@ -994,13 +996,7 @@ PRIVATE struct state *getstate(struct lemon *lemp)
stp->cfp = cfp; /* Remember the configuration closure */
stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
stp->ap = 0; /* No actions, yet. */
#ifndef NDEBUG
int ret =
#endif
State_insert(stp,stp->bp); /* Add to the state table */
#ifndef NDEBUG
assert(ret == 1); /* CSA hint: stp did not leak, it has escaped. */
#endif
buildshifts(lemp,stp); /* Recursively compute successor states */
}
return stp;
@ -1034,7 +1030,7 @@ PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
struct state *newstp; /* A pointer to a successor state */
/* Each configuration becomes complete after it contibutes to a successor
/* Each configuration becomes complete after it contributes to a successor
** state. Initially, all configurations are incomplete */
for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
@ -1090,8 +1086,7 @@ void FindLinks(struct lemon *lemp)
** which the link is attached. */
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
assert(stp); /* Hint for CSA */
for(cfp=stp->cfp; cfp; cfp=cfp->next){
for(cfp=stp?stp->cfp:0; cfp; cfp=cfp->next){
cfp->stp = stp;
}
}
@ -1100,7 +1095,7 @@ void FindLinks(struct lemon *lemp)
** links are used in the follow-set computation. */
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
for(cfp=stp->cfp; cfp; cfp=cfp->next){
for(cfp=stp?stp->cfp:0; cfp; cfp=cfp->next){
for(plp=cfp->bplp; plp; plp=plp->next){
other = plp->cfp;
Plink_add(&other->fplp,cfp);
@ -1123,6 +1118,7 @@ void FindFollowSets(struct lemon *lemp)
int change;
for(i=0; i<lemp->nstate; i++){
assert( lemp->sorted[i]!=0 );
for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
cfp->status = INCOMPLETE;
}
@ -1131,6 +1127,7 @@ void FindFollowSets(struct lemon *lemp)
do{
progress = 0;
for(i=0; i<lemp->nstate; i++){
assert( lemp->sorted[i]!=0 );
for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
if( cfp->status==COMPLETE ) continue;
for(plp=cfp->fplp; plp; plp=plp->next){
@ -1180,7 +1177,14 @@ void FindActions(struct lemon *lemp)
/* Add the accepting token */
if( lemp->start ){
sp = Symbol_find(lemp->start);
if( sp==0 ) sp = lemp->startRule->lhs;
if( sp==0 ){
if( lemp->startRule==0 ){
fprintf(stderr, "internal error on source line %d: no start rule\n",
__LINE__);
exit(1);
}
sp = lemp->startRule->lhs;
}
}else{
sp = lemp->startRule->lhs;
}
@ -1307,21 +1311,7 @@ static struct config **basisend = 0; /* End of list of basis configs */
/* Return a pointer to a new configuration */
PRIVATE struct config *newconfig(void){
struct config *newcfg;
if( freelist==0 ){
int i;
int amt = 3;
freelist = (struct config *)calloc( amt, sizeof(struct config) );
if( freelist==0 ){
fprintf(stderr,"Unable to allocate memory for a new configuration.");
exit(1);
}
for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
freelist[amt-1].next = 0;
}
newcfg = freelist;
freelist = freelist->next;
return newcfg;
return (struct config*)calloc(1, sizeof(struct config));
}
/* The configuration "old" is no longer used */
@ -1703,7 +1693,6 @@ int main(int argc, char **argv){
/* Parse the input file */
Parse(&lem);
if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
assert(lem.rule); /* Hint for CSA (no errors => rule found). */
if( lem.nrule==0 ){
fprintf(stderr,"Empty grammar.\n");
exit(1);
@ -1896,7 +1885,7 @@ static char *merge(
**
** Return Value:
** A pointer to the head of a sorted list containing the elements
** orginally in list.
** originally in list.
**
** Side effects:
** The "next" pointers for elements in list are changed.
@ -1941,8 +1930,12 @@ static FILE *errstream;
static void errline(int n, int k, FILE *err)
{
int spcnt, i;
if( g_argv[0] ) fprintf(err,"%s",g_argv[0]);
spcnt = lemonStrlen(g_argv[0]) + 1;
if( g_argv[0] ){
fprintf(err,"%s",g_argv[0]);
spcnt = lemonStrlen(g_argv[0]) + 1;
}else{
spcnt = 0;
}
for(i=1; i<n && g_argv[i]; i++){
fprintf(err," %s",g_argv[i]);
spcnt += lemonStrlen(g_argv[i])+1;
@ -2717,7 +2710,7 @@ static void parseonetoken(struct pstate *psp)
** in order to control their assigned integer number. The number for
** each token is assigned when it is first seen. So by including
**
** %token ONE TWO THREE
** %token ONE TWO THREE.
**
** early in the grammar file, that assigns small consecutive values
** to each of the tokens ONE TWO and THREE.
@ -3022,6 +3015,7 @@ void Parse(struct lemon *gp)
}
if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
cp+=2;
if( (*cp)=='/' ) cp++;
while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
if( c=='\n' ) lineno++;
cp++;
@ -3522,7 +3516,7 @@ void ReportOutput(struct lemon *lemp)
}
/* Search for the file "name" which is in the same directory as
** the exacutable */
** the executable */
PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
{
const char *pathlist;
@ -3547,7 +3541,6 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
MemoryCheck(pathbuf); MemoryCheck(path); /* Fail on allocation failure. */
if( (pathbuf != 0) && (path!=0) ){
pathbufptr = pathbuf;
lemon_strcpy(pathbuf, pathlist);
@ -3581,7 +3574,9 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
/* Since a SHIFT is inherient after a prior REDUCE, convert any
** SHIFTREDUCE action with a nonterminal on the LHS into a simple
** REDUCE action: */
if( ap->sp->index>=lemp->nterminal ){
if( ap->sp->index>=lemp->nterminal
&& (lemp->errsym==0 || ap->sp->index!=lemp->errsym->index)
){
act = lemp->minReduce + ap->x.rp->iRule;
}else{
act = lemp->minShiftReduce + ap->x.rp->iRule;
@ -3878,7 +3873,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
lhsdirect = 1;
}else if( rp->rhsalias[0]==0 ){
/* The left-most RHS symbol has no value. LHS direct is ok. But
** we have to call the distructor on the RHS symbol first. */
** we have to call the destructor on the RHS symbol first. */
lhsdirect = 1;
if( has_destructor(rp->rhs[0],lemp) ){
append_str(0,0,0,0);
@ -4296,7 +4291,6 @@ void ReportTable(
int sqlFlag /* Generate the *.sql file too */
){
FILE *out, *in, *sql;
char line[LINESIZE];
int lineno;
struct state *stp;
struct action *ap;
@ -4771,7 +4765,6 @@ void ReportTable(
/* Generate a table containing the symbolic name of every symbol
*/
for(i=0; i<lemp->nsymbol; i++){
lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
@ -4859,7 +4852,7 @@ void ReportTable(
** yyRuleInfoNRhs[].
**
** Note: This code depends on the fact that rules are number
** sequentually beginning with 0.
** sequentially beginning with 0.
*/
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
fprintf(out," %4d, /* (%d) ", rp->lhs->index, i);
@ -5347,8 +5340,9 @@ int Strsafe_insert(const char *data)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
free(x1a->tbl);
memcpy(x1a, &array, sizeof(array)); /* *x1a = array; */
/* free(x1a->tbl); // This program was originally for 16-bit machines.
** Don't worry about freeing memory on modern platforms. */
*x1a = array;
}
/* Insert the new data */
h = ph & (x1a->size-1);
@ -5515,8 +5509,10 @@ int Symbol_insert(struct symbol *data, const char *key)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
free(x2a->tbl);
memcpy(x2a, &array, sizeof(array)); /* *x2a = array; */
/* free(x2a->tbl); // This program was originally written for 16-bit
** machines. Don't worry about freeing this trivial amount of memory
** on modern platforms. Just leak it. */
*x2a = array;
}
/* Insert the new data */
h = ph & (x2a->size-1);
@ -5713,7 +5709,7 @@ int State_insert(struct state *data, struct config *key)
array.ht[h] = newnp;
}
free(x3a->tbl);
memcpy(x3a, &array, sizeof(array)); /* *x3a = array; */
*x3a = array;
}
/* Insert the new data */
h = ph & (x3a->size-1);
@ -5851,8 +5847,10 @@ int Configtable_insert(struct config *data)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
free(x4a->tbl);
memcpy(x4a, &array, sizeof(array)); /* *x4a = array; */
/* free(x4a->tbl); // This code was originall written for 16-bit machines.
** on modern machines, don't worry about freeing this trival amount of
** memory. */
*x4a = array;
}
/* Insert the new data */
h = ph & (x4a->size-1);

View File

@ -1,33 +0,0 @@
/* This file is #include'd at the top of a Lex/Flex scanner
for use with the Lemon parser. You must have #define'd:
LVAL name of lval variable
LVAL_TYPE type of lval variable
LVAL_INIT_VAL Initial value of lval variable
*/
/* Flex has a few routines which help us get the scanner to read
* from a string rather than from a file. POSIX lex only provides
* for reading from a file; any method of reading from a string
* is inherently non-portable. Besides reading from a string,
* we have to worry about resetting the scanner after a bad
* parse; this too is non-portable. Combine the reset with
* a string input, and you have major non-portability. I'll provide
* the routines for flex here. If you really want to modify the
* scanner and use a non-flex lex implementation, you may
* add more ifdef's below.
*/
/* If we don't need yyunput, use this macro to get it out of the
* generated C file, avoiding a compiler warning about its lack of use */
#define YY_NO_UNPUT 1
/* Yup, I'm using a non-standard type for lval, unlike usual lex/yacc implementations.
* I can do so because I'm *not* using yacc, I'm using Lemon, where I have
* more control of the interaction between scanner and parser. */
LVAL_TYPE LVAL = LVAL_INIT_VAL;

View File

@ -1,77 +0,0 @@
/* This file is #include'd at the bottom of a Lex/Flex scanner
for use with the Lemon parser. You must have #define'd:
MODNAME module name for creating function names:
Prototypes:
*/
void CONCAT(MODNAME,_scanner_text(char *text));
void CONCAT(MODNAME,_scanner_file(FILE *fh));
void CONCAT(MODNAME,_scanner_cleanup(void));
#ifndef YY_SKIP_YYWRAP
int CONCAT(MODNAME,_wrap(void));
#endif
#include <cppmagic.h>
#define TEXT_FUNC CONCAT(MODNAME,_scanner_text)
#define FILE_FUNC CONCAT(MODNAME,_scanner_file)
#define CLEANUP_FUNC CONCAT(MODNAME,_scanner_cleanup)
#ifndef YY_SKIP_YYWRAP
#define WRAP_FUNC CONCAT(MODNAME,_wrap)
#endif
/* flex 2.5.31 no longer #defines these as yy_* if used with -P. */
#ifndef yy_scan_string
#define yy_scan_string CONCAT(FLEX_YY_PREFIX, _scan_string)
#endif
#ifndef yy_create_buffer
#define yy_create_buffer CONCAT(FLEX_YY_PREFIX, _create_buffer)
#endif
#ifndef yy_switch_to_buffer
#define yy_switch_to_buffer CONCAT(FLEX_YY_PREFIX, _switch_to_buffer)
#endif
#ifndef yy_delete_buffer
#define yy_delete_buffer CONCAT(FLEX_YY_PREFIX, _delete_buffer)
#endif
/* Resets scanner and assigns the char* argument
* as the text to scan
*/
void
TEXT_FUNC (char *text)
{
yy_scan_string(text);
}
void
FILE_FUNC (FILE* fh)
{
YY_BUFFER_STATE new_buffer;
new_buffer = yy_create_buffer(fh, YY_BUF_SIZE);
yy_switch_to_buffer(new_buffer);
}
void
CLEANUP_FUNC (void)
{
BEGIN(INITIAL);
yy_delete_buffer(YY_CURRENT_BUFFER);
}
#ifndef YY_SKIP_YYWRAP
/* Flex has an option '%option noyywrap' so that I don't have to
* provide this yywrap function, but in order to maintain portability,
* I'll just use this yywrap() function if that option wasn't used.
*/
int
WRAP_FUNC (void)
{
return 1; /* stop at EOF, instead of looking for next file */
}
#endif

View File

@ -223,9 +223,9 @@ struct yyParser {
};
typedef struct yyParser yyParser;
#include <assert.h>
#ifndef NDEBUG
#include <stdio.h>
#include <assert.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
@ -317,7 +317,7 @@ static int yyGrowStack(yyParser *p){
/* Initialize a new parser that has already been allocated.
*/
static void ParseInit(void *yypRawParser ParseCTX_PDECL){
void ParseInit(void *yypRawParser ParseCTX_PDECL){
yyParser *yypParser = (yyParser*)yypRawParser;
ParseCTX_STORE
#ifdef YYTRACKMAXSTACKDEPTH
@ -424,7 +424,7 @@ static void yy_pop_parser_stack(yyParser *pParser){
/*
** Clear all secondary memory allocations from the parser
*/
static void ParseFinalize(void *p){
void ParseFinalize(void *p){
yyParser *pParser = (yyParser*)p;
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
@ -718,55 +718,6 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
#ifndef NDEBUG
if( yyTraceFILE ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yymsp[yysize].stateno);
}else{
fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yytos>=yypParser->yystackEnd ){
yyStackOverflow(yypParser);
/* The call to yyStackOverflow() above pops the stack until it is
** empty, causing the main parser loop to exit. So the return value
** is never used and does not matter. */
return 0;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
if( yyGrowStack(yypParser) ){
yyStackOverflow(yypParser);
/* The call to yyStackOverflow() above pops the stack until it is
** empty, causing the main parser loop to exit. So the return value
** is never used and does not matter. */
return 0;
}
yymsp = yypParser->yytos;
}
#endif
}
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
@ -831,7 +782,7 @@ static void yy_parse_failed(
*/
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
int yymajor _U_, /* The major type of the error token */
int yymajor, /* The major type of the error token */
ParseTOKENTYPE yyminor /* The minor type of the error token */
){
ParseARG_FETCH
@ -925,12 +876,56 @@ void Parse(
}
#endif
do{
while(1){ /* Exit by "break" */
assert( yypParser->yytos>=yypParser->yystack );
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
yyminor ParseCTX_PARAM);
unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
#ifndef NDEBUG
assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
if( yyTraceFILE ){
int yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yypParser->yytos[yysize].stateno);
}else{
fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
assert( yypParser->yyhwm ==
(int)(yypParser->yytos - yypParser->yystack));
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yytos>=yypParser->yystackEnd ){
yyStackOverflow(yypParser);
break;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
if( yyGrowStack(yypParser) ){
yyStackOverflow(yypParser);
break;
}
}
#endif
}
yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor ParseCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
@ -986,14 +981,13 @@ void Parse(
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
yymajor = YYNOCODE;
}else{
while( yypParser->yytos >= yypParser->yystack
&& (yyact = yy_find_reduce_action(
yypParser->yytos->stateno,
YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
){
while( yypParser->yytos > yypParser->yystack ){
yyact = yy_find_reduce_action(yypParser->yytos->stateno,
YYERRORSYMBOL);
if( yyact<=YY_MAX_SHIFTREDUCE ) break;
yy_pop_parser_stack(yypParser);
}
if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
if( yypParser->yytos <= yypParser->yystack || yymajor==0 ){
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
@ -1043,7 +1037,7 @@ void Parse(
break;
#endif
}
}while( yypParser->yytos>yypParser->yystack );
}
#ifndef NDEBUG
if( yyTraceFILE ){
yyStackEntry *i;
@ -1059,7 +1053,6 @@ void Parse(
return;
}
#if 0
/*
** Return the fallback token corresponding to canonical token iToken, or
** 0 if iToken has no fallback.
@ -1073,4 +1066,3 @@ int ParseFallback(int iToken){
return 0;
#endif
}
#endif

View File

@ -1,49 +0,0 @@
Make ParseInit and ParseFinalize static to fix -Wmissing-prototypes in
dtd_grammar.c. Hide ParseFallback to fix -Wunused-function since this feature
is not used by Wireshark.
Mark yymajor as _U_ since none of the lemon grammar files seem to use it in
their %syntax_error directive, this fixes -Wunused-parameter
SPDX-License-Identifier: CC0-1.0
--- a/lempar.c
+++ b/lempar.c
@@ -317,7 +317,7 @@ static int yyGrowStack(yyParser *p){
/* Initialize a new parser that has already been allocated.
*/
-void ParseInit(void *yypRawParser ParseCTX_PDECL){
+static void ParseInit(void *yypRawParser ParseCTX_PDECL){
yyParser *yypParser = (yyParser*)yypRawParser;
ParseCTX_STORE
#ifdef YYTRACKMAXSTACKDEPTH
@@ -424,7 +424,7 @@ static void yy_pop_parser_stack(yyParser *pParser){
/*
** Clear all secondary memory allocations from the parser
*/
-void ParseFinalize(void *p){
+static void ParseFinalize(void *p){
yyParser *pParser = (yyParser*)p;
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
@@ -831,7 +831,7 @@ static void yy_parse_failed(
*/
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
- int yymajor, /* The major type of the error token */
+ int yymajor _U_, /* The major type of the error token */
ParseTOKENTYPE yyminor /* The minor type of the error token */
){
ParseARG_FETCH
@@ -1059,6 +1059,7 @@ void Parse(
return;
}
+#if 0
/*
** Return the fallback token corresponding to canonical token iToken, or
** 0 if iToken has no fallback.
@@ -1072,3 +1073,4 @@ int ParseFallback(int iToken){
return 0;
#endif
}
+#endif

View File

@ -1,13 +0,0 @@
Avoid dead store warning, the same assignment happens later in this function.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -4090,7 +4101,7 @@ void print_stack_union(
int *plineno, /* Pointer to the line number */
int mhflag /* True if generating makeheaders output */
){
- int lineno = *plineno; /* The line number of the output */
+ int lineno; /* The line number of the output */
char **types; /* A hash table of datatypes */
int arraysize; /* Size of the "types" array */
int maxdtlength; /* Maximum length of any ".datatype" field. */

View File

@ -1,34 +0,0 @@
Assertions to avoid false null-pointer dereferences.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -695,11 +695,13 @@ int acttab_insert(acttab *p, int makeItSafe){
fprintf(stderr,"malloc failed\n");
exit(1);
}
+ assert(oldAlloc < p->nActionAlloc); /* hint for CSA */
for(i=oldAlloc; i<p->nActionAlloc; i++){
p->aAction[i].lookahead = -1;
p->aAction[i].action = -1;
}
}
+ assert(p->aAction); /* Hint for CSA (for p->aAction[i] below) */
/* Scan the existing action table looking for an offset that is a
** duplicate of the current transaction set. Fall out of the loop
@@ -1083,6 +1091,7 @@ void FindLinks(struct lemon *lemp)
** which the link is attached. */
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
+ assert(stp); /* Hint for CSA */
for(cfp=stp->cfp; cfp; cfp=cfp->next){
cfp->stp = stp;
}
@@ -1695,6 +1704,7 @@ int main(int argc, char **argv)
/* Parse the input file */
Parse(&lem);
if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
+ assert(lem.rule); /* Hint for CSA (no errors => rule found). */
if( lem.nrule==0 ){
fprintf(stderr,"Empty grammar.\n");
exit(1);

View File

@ -1,45 +0,0 @@
Workaround for CSA limitation, it currently does not correctly handle structure
assignment. Escaping the pointer via function call is a workaround to hide the
false positive (use-after-free). Change done with:
sed -e 's#\*\(x[1-4]a\) = array;$#memcpy(\1, \&array, sizeof(array)); /* & */#'
Link: https://bugs.llvm.org/show_bug.cgi?id=39356
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -5338,7 +5349,7 @@ int Strsafe_insert(const char *data)
array.ht[h] = newnp;
}
free(x1a->tbl);
- *x1a = array;
+ memcpy(x1a, &array, sizeof(array)); /* *x1a = array; */
}
/* Insert the new data */
h = ph & (x1a->size-1);
@@ -5506,7 +5517,7 @@ int Symbol_insert(struct symbol *data, const char *key)
array.ht[h] = newnp;
}
free(x2a->tbl);
- *x2a = array;
+ memcpy(x2a, &array, sizeof(array)); /* *x2a = array; */
}
/* Insert the new data */
h = ph & (x2a->size-1);
@@ -5703,7 +5714,7 @@ int State_insert(struct state *data, struct config *key)
array.ht[h] = newnp;
}
free(x3a->tbl);
- *x3a = array;
+ memcpy(x3a, &array, sizeof(array)); /* *x3a = array; */
}
/* Insert the new data */
h = ph & (x3a->size-1);
@@ -5842,7 +5853,7 @@ int Configtable_insert(struct config *data)
array.ht[h] = newnp;
}
free(x4a->tbl);
- *x4a = array;
+ memcpy(x4a, &array, sizeof(array)); /* *x4a = array; */
}
/* Insert the new data */
h = ph & (x4a->size-1);

View File

@ -1,12 +0,0 @@
Avoid leaking pathbuf when path==0 by marking allocation failures as fatal.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -3538,6 +3548,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
+ MemoryCheck(pathbuf); MemoryCheck(path); /* Fail on allocation failure. */
if( (pathbuf != 0) && (path!=0) ){
pathbufptr = pathbuf;
lemon_strcpy(pathbuf, pathlist);

View File

@ -1,20 +0,0 @@
CSA thought that stp would leak if State_insert returns early: when x3a is NULL
(memory allocation failure) or when the state existed before (cannot happen for
the initial state). So annotate it as such.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -993,7 +995,13 @@ PRIVATE struct state *getstate(struct lemon *lemp)
stp->cfp = cfp; /* Remember the configuration closure */
stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
stp->ap = 0; /* No actions, yet. */
+#ifndef NDEBUG
+ int ret =
+#endif
State_insert(stp,stp->bp); /* Add to the state table */
+#ifndef NDEBUG
+ assert(ret == 1); /* CSA hint: stp did not leak, it has escaped. */
+#endif
buildshifts(lemp,stp); /* Recursively compute successor states */
}
return stp;