mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-09-10 20:29:58 +00:00
Protect against function-looking pointers inside struct definitions (Fix #399)
This commit is contained in:
@@ -251,6 +251,8 @@ class CMockHeaderParser
|
||||
source.gsub!(/^\s*#.*/, '')
|
||||
|
||||
# enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them
|
||||
# pre-collapse nested brace pairs so that structs containing nested structs/unions are removed as a unit below
|
||||
source = remove_nested_pairs_of_braces(source) unless cpp
|
||||
# forward declared structs are removed before struct definitions so they don't mess up real thing later. we leave structs keywords in function prototypes
|
||||
source.gsub!(/^[\w\s]*struct[^;{}()]+;/m, '') # remove forward declared structs
|
||||
source.gsub!(/^[\w\s]*(enum|union|struct|typedef)[\w\s()]*\{[^}]+\}[\w\s*,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# =========================================================================
|
||||
# CMock - Automatic Mock Generation for C
|
||||
# ThrowTheSwitch.org
|
||||
# Copyright (c) 2007-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
|
||||
# SPDX-License-Identifier: MIT
|
||||
# =========================================================================
|
||||
|
||||
---
|
||||
#The purpose of this test is to verify that structs containing function pointer
|
||||
#members are not mistakenly mocked by CMock. Only actual function prototypes
|
||||
#at file scope should be mocked. This is especially tricky when the struct
|
||||
#contains nested anonymous structs or unions, because the struct removal regex
|
||||
#can be confused by the inner closing brace and leave function pointer members
|
||||
#in the source for the parser to encounter.
|
||||
:cmock:
|
||||
:plugins:
|
||||
- # none
|
||||
:includes:
|
||||
- "<stdint.h>"
|
||||
|
||||
:systest:
|
||||
:types: |
|
||||
#include <stdint.h>
|
||||
|
||||
/* Forward-declare the type so the source header can use SaladBowl* before
|
||||
the full definition (which lives in the mockable header) is visible. */
|
||||
typedef struct SaladBowlStruct SaladBowl;
|
||||
|
||||
:mockable: |
|
||||
#include <stdint.h>
|
||||
|
||||
/* Full struct definition with a nested anonymous struct and function pointer
|
||||
members. CMock must ignore all of these and only mock saladBowlInit. */
|
||||
struct SaladBowlStruct {
|
||||
struct {
|
||||
uint16_t remainingCapacity;
|
||||
uint16_t ingredientCount;
|
||||
} stats;
|
||||
|
||||
void* (*toss)(struct SaladBowlStruct *self, uint16_t itemSize);
|
||||
int32_t (*empty)(struct SaladBowlStruct *self);
|
||||
void* (*grab)(struct SaladBowlStruct *self, uint16_t itemIndex);
|
||||
void* (*add)(struct SaladBowlStruct *self, uint16_t itemIndex, uint16_t itemSize);
|
||||
int32_t (*pluck)(struct SaladBowlStruct *self, uint16_t itemIndex);
|
||||
};
|
||||
|
||||
int32_t saladBowlInit(SaladBowl *bowl, uint16_t sizeInBytes, uint16_t headerSizeInBytes);
|
||||
|
||||
:source:
|
||||
:header: |
|
||||
#include <stdint.h>
|
||||
void exercise_salad_bowl(SaladBowl *bowl);
|
||||
|
||||
:code: |
|
||||
void exercise_salad_bowl(SaladBowl *bowl)
|
||||
{
|
||||
saladBowlInit(bowl, 256, 16);
|
||||
}
|
||||
|
||||
:tests:
|
||||
:common: |
|
||||
SaladBowl g_bowl;
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
:units:
|
||||
- :pass: TRUE
|
||||
:should: 'mock only saladBowlInit and ignore function pointer members of the struct'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
saladBowlInit_ExpectAndReturn(&g_bowl, 256, 16, 0);
|
||||
exercise_salad_bowl(&g_bowl);
|
||||
}
|
||||
|
||||
...
|
||||
Reference in New Issue
Block a user