Splint - Secure Programming Lint |
|
Download - Documentation - Manual - Links | Sponsors - Credits |
Iterators
Changes from Weak Checks
DifferencesThe anomalies detected in weak mode have been corrected:
- Unused variable declarations removed
- Changed type of maxEmployeeName to size_t
- Used call to int_toUnsigned to check argument to malloc
- Fixed abstract violations by using calls to eref_equal
- Added assert to check result of hire call is db_OK
- Suppressed modification errors by using syntactic comments in the code (and fixed the one that used return inside the loop)
Now, running LCLint with weak checking detects no errors.
Modules
- employee - employee datatype (LCL, Code, Header)
- empset - sets of employees (LCL, Code, Header)
- dbase - database of employees (LCL, Code, Header)
- eref - reference to an employee (LCL, Code, Header)
- erc - collection of erefs (LCL, Code, Header)
- ereftab - table of employees and erefs (LCL, Code, Header)
Using Iterators
We had to suppress the modification errors because they used generators to go through a collection. Instead, we can use stylized iterators. This has the advantage that LCLint will check the definition and use of the iterator, and the iterator is now clearly documented.The original code uses the for_ercElems macro to iterate through the elements of an erc. This requires modifying the erc, creating an instance of the ercIter type, and destroying the ercIter at the end of the loop to restore the erc to its original state.
Instead, we define an iterator that goes through each element of the erc, assigning a variable to the new element for each iteration. The specification for erc_elements is:
iter erc_elements (erc c, yield eref el);This could also be expressed directly in the C source or header file, as:/*@iter erc_elements (erc c, yield eref el);@*/The yield parameter, el is assigned a value corresponding to a different elements of the erc each time through the loop.Now we can rewrite the code to use the iterator. For example, the loop in _db_ercKeyGet:
eref _db_ercKeyGet (erc c, int key) { eref er; ercIter it; for_ercElems (er, it, c) { if (eref_get (er).ssNum == key) { erc_iterReturn (it, er); } } return erefNIL; }is rewritten as:static eref _db_ercKeyGet(erc c, int key) { erc_elements(c, er) { if (eref_get(er).ssNum == key) return (er); } end_erc_elements ; return erefNIL; }The erc_elements iterator and its matching end are defined using macros:
# define erc_elements(c, m_x) \ { erc m_c = (c); ercElem *m_ec = (m_c)->vals; unsigned int m_i = 0; \ while (m_i < (m_c)->size) { \ eref m_x = m_ec->val; m_ec = m_ec->next; m_i++; # define end_erc_elements }}Similarly, empset_elements, erc_elements and ereftab_element are used to iterate through other collection types.
|