Multi-threaded Java application demo
Preventing Buffer Overflow in C/C++
How does memory work across different levels of scope and what is a safe way to pass, store, and alter that memory given different levels of input? Well, I think this is another way of saying, how do I prevent buffer overflow?
For example, I want to create a function called
int ecsGetComponentBit(componentTypeE value) that returns an integer value
representing which component bit (0-32) is set. I have an enumeration representing a
32-bit mask field of the different component types. Here is the enum and struct:
// component.h
typedef enum componentTypeE {
COMPONENT_NONE = 0,
COMPONENT_TYPE_COUNT = 6,
COMPONENT_SET1_RENDER2D = 1u << 0,
COMPONENT_SET1_KEYBOARD = 1u << 1,
COMPONENT_SET1_MOUSE = 1u << 2,
COMPONENT_SET1_POSITION = 1u << 3,
COMPONENT_SET1_VELOCITY = 1u << 4,
COMPONENT_SET1_NAMETAG = 1u << 5,
} componentTypeE;
typedef struct componentT {
componentTypeE type;
void* data;
} componentT;
Now, here is the problematic code:
int ecsGetComponentBit(componentTypeE value) {
char msg[512];
char componentName[200];
int position = 1;
Uint32 i = 1;
while (1) {
if (i == (Uint32)value) {
return position;
}
i *= 2;
position++;
if (position >= 32) {
ecsGetComponentName(value, componentName);
sprintf(msg,
"warning in function ecsGetComponentBit() - componentType:%s is not correctly initialized",
componentName);
writeToLog(msg, "runlog.txt");
break;
}
}
return -1;
}
void ecsGetComponentName(componentTypeE componentType, char* name) {
if (name == NULL) return;
if (componentType == COMPONENT_SET1_KEYBOARD) {
sprintf(name, "COMPONENT_SET1_KEYBOARD");
} else if (componentType == COMPONENT_SET1_MOUSE) {
sprintf(name, "COMPONENT_SET1_MOUSE");
} else if (componentType == COMPONENT_SET1_RENDER2D) {
sprintf(name, "COMPONENT_SET1_RENDER2D");
} else if (componentType == COMPONENT_SET1_VELOCITY) {
sprintf(name, "COMPONENT_SET1_VELOCITY");
} else if (componentType == COMPONENT_SET1_POSITION) {
sprintf(name, "COMPONENT_SET1_POSITION");
} else if (componentType == COMPONENT_SET1_NAMETAG) {
sprintf(name, "COMPONENT_SET1_NAMETAG");
} else {
sprintf(name, "UNKNOWN_COMPONENT(bit:%d)", ecsGetComponentBit(componentType));
}
}
To be honest, I've only dug into this issue because MSVC wasn't letting me build. You set the
component name here depending on the type and save it back into the char* array
that was passed into the function — the problem is that if you set a string larger than the
incoming buffer, you will get a buffer overflow.
In the case of ecsGetComponentBit() usage, I've allocated 200 chars of memory
to be used as a buffer, which is safe in this instance, but without safeguards, it could be
risky.
How do we fix it? Pretty simple — use sprintf_s() instead of sprintf().
This requires specifying the buffer size, which prevents overflow. Here’s the fixed version:
int ecsGetComponentBit(componentTypeE value) {
char msg[512];
char componentName[200];
int position = 1;
Uint32 i = 1;
while (1) {
if (i == (Uint32)value) return position;
i *= 2;
position++;
if (position >= 32) {
ecsGetComponentName(value, componentName, sizeof(componentName));
sprintf_s(msg, sizeof(msg),
"warning in function ecsGetComponentBit() - componentType:%s is not correctly initialized",
componentName);
writeToLog(msg, "runlog.txt");
break;
}
}
return -1;
}
void ecsGetComponentName(componentTypeE componentType, char* name, size_t nameSize) {
if (name == NULL || nameSize == 0) return;
if (componentType == COMPONENT_SET1_KEYBOARD) {
sprintf_s(name, nameSize, "COMPONENT_SET1_KEYBOARD");
} else if (componentType == COMPONENT_SET1_MOUSE) {
sprintf_s(name, nameSize, "COMPONENT_SET1_MOUSE");
} else if (componentType == COMPONENT_SET1_RENDER2D) {
sprintf_s(name, nameSize, "COMPONENT_SET1_RENDER2D");
} else if (componentType == COMPONENT_SET1_VELOCITY) {
sprintf_s(name, nameSize, "COMPONENT_SET1_VELOCITY");
} else if (componentType == COMPONENT_SET1_POSITION) {
sprintf_s(name, nameSize, "COMPONENT_SET1_POSITION");
} else if (componentType == COMPONENT_SET1_NAMETAG) {
sprintf_s(name, nameSize, "COMPONENT_SET1_NAMETAG");
} else {
sprintf_s(name, nameSize, "UNKNOWN_COMPONENT(bit:%d)", ecsGetComponentBit(componentType));
}
}
Doing things this way is not only fast, but safe. I hope that thinking about memory in this way was enlightening. Have a great day!
3D Interactive Cube
• F/G to increase/decrease delta
• A/S/D or Z/X/C to pick axis & apply
• R to reset
Blog Posts
- C++ Buffer Overflow August 14, 2025
- Client-Server Architecture November, 2024
- Face Detection Application November, 2024
- Computing Convolution Kernels October, 2024
- Interactive Bezier Curve May, 2023
About Me
Hi, I'm Tony. I recently completed my Masters degree in Computer Science from Drexel University.
Contact: tonystanell [at] gmail [dot] com