Boundary Value Bugs in Software Testing: Three Typical Cases and Their Fixes
The article reviews three common boundary‑value bugs encountered during software testing, explains why they occur, shows the original C code that triggers each issue, and provides concise corrections to prevent off‑by‑one errors and buffer overflows.
Long‑term testing experience shows that most errors happen at the edges of input or output ranges rather than inside them. This second article in a series presents three typical boundary‑value bugs, their root causes, and simple fixes.
Bug 1 – Buffer Size Check
Bug description: When checking whether a destination buffer can hold a formatted string, the condition fails to account for the terminating null character, causing the last character to be dropped when sprintf writes the data.
if((size_t)dest_size < strlen(idc) + strlen(host) + strlen(tmp))
{
LOG_ERR("%s failed. Dest buffer_size is not enough.",_func_);
return ERR_BUF_NOT_ENOUGH;
}The code intends to reject insufficient space, but because the null terminator is ignored, a buffer that is exactly the needed size is considered sufficient, leading to truncation.
Solution: Change the comparison to <= so the null byte is counted.
Bug 2 – Retry Counter Off‑by‑One
Bug description: When sending a message, the retry loop increments try_send_times after the check, causing the actual number of attempts to exceed the configured maximum by one.
if (status == -1)
{
// send message failed
if (errno == EAGAIN)
{
if (try_send_times < MAX_SEND_MSG_TIMES)
{
LOG_WARN("msg queue is full! try_send_times:%d",try_send_times);
usleep(5000);
try_send_times++;
continue;
}
else
{
LOG_ERR("msg queue is full! try send message times are larger than MAX TIMES: %d",MAX_SEND_MSG_TIMES);
}
}
else
{
LOG_ERR("Send msg failed! Err: %s", strerror(errno));
}
}The loop exits after the condition fails, but the counter has already been incremented, resulting in MAX_SEND_MSG_TIMES + 1 attempts.
Solution: Initialise try_send_times to 1 (or adjust the logic so the increment happens only after a successful retry).
Bug 3 – Increment Inside Condition
Bug description: Using a post‑increment operator in the condition ( if(try_get_times++ < _max_repeat_read_times) ) makes the counter increase even when the condition is false, so the final logged count is one higher than the actual limit.
if(try_get_times++ < _max_repeat_read_times)
{
...
}
...
if (try_get_times >= _max_repeat_read_times)
{
LOG_ERR("%s: Error value of key: %s, Execute %d times", __func__,key, try_get_times);
}Each evaluation increments try_get_times , so after the loop the logged value becomes _max_repeat_read_times + 1 .
Solution: Move the increment inside the if block or log _max_repeat_read_times instead of the incremented variable.
Conclusion
These examples illustrate that boundary‑value problems often hide in seemingly trivial checks or loop conditions. Testers should examine not only the explicit conditions but also the surrounding logic, and apply defensive coding practices to avoid off‑by‑one and buffer‑size errors.
360 Tech Engineering
Official tech channel of 360, building the most professional technology aggregation platform for the brand.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.