HOME

TheInfoList



OR:

An off-by-one error or off-by-one bug (known by acronyms OBOE, OBO, OB1 and OBOB) is a
logic error In computer programming, a logic error is a bug in a program that causes it to operate incorrectly, but not to terminate abnormally (or crash). A logic error produces unintended or undesired output or other behaviour, although it may not immed ...
involving the discrete equivalent of a
boundary condition In mathematics, in the field of differential equations, a boundary value problem is a differential equation together with a set of additional constraints, called the boundary conditions. A solution to a boundary value problem is a solution to t ...
. It often occurs in computer programming when an iterative loop iterates one time too many or too few. This problem could arise when a programmer makes mistakes such as using "is less than or equal to" where "is less than" should have been used in a comparison, or fails to take into account that a sequence starts at zero rather than one (as with array indices in many languages). This can also occur in a
mathematical Mathematics is an area of knowledge that includes the topics of numbers, formulas and related structures, shapes and the spaces in which they are contained, and quantities and their changes. These topics are represented in modern mathematics ...
context.


Cases


Looping over arrays

Consider an
array An array is a systematic arrangement of similar objects, usually in rows and columns. Things called an array include: {{TOC right Music * In twelve-tone and serial composition, the presentation of simultaneous twelve-tone sets such that the ...
of items, and items ''m'' through ''n'' (inclusive) are to be processed. How many items are there? An intuitive answer may be ''n'' − ''m'', but that is off by one, exhibiting a
fencepost error An off-by-one error or off-by-one bug (known by acronyms OBOE, OBO, OB1 and OBOB) is a logic error involving the discrete equivalent of a boundary condition. It often occurs in computer programming when an iterative loop iterates one time too ...
; the correct answer is (''n'' – ''m'') + 1. For this reason, ranges in computing are often represented by
half-open interval In mathematics, a (real) interval is a set of real numbers that contains all real numbers lying between any two numbers of the set. For example, the set of numbers satisfying is an interval which contains , , and all numbers in between. Other ...
s; the range from ''m'' to ''n'' (inclusive) is represented by the range from ''m'' (inclusive) to ''n'' + 1 (exclusive) to avoid fencepost errors. For example, a loop that iterates five times (from 0 to 4 inclusive) can be written as a half-open interval from 0 to 5: for (index = 0; index < 5; index++) The loop body is executed first of all with equal to 0; then becomes 1, 2, 3, and finally 4 on successive iterations. At that point, becomes 5, so is false and the loop ends. However, if the comparison used were <= (less than or equal to), the loop would be carried out six times: takes the values 0, 1, 2, 3, 4, and 5. Likewise, if were initialized to 1 rather than 0, there would only be four iterations: takes the values 1, 2, 3, and 4. Both of these alternatives can cause off-by-one errors. Another such error can occur if a do-while loop is used in place of a
while loop In most computer programming languages, a while loop is a control flow statement that allows code to be executed repeatedly based on a given Boolean condition. The ''while'' loop can be thought of as a repeating if statement. Overview The '' ...
(or vice versa.) A do-while loop is guaranteed to run at least once. Array-related confusion may also result from differences in programming languages. Numbering from 0 is most common, but some languages start array numbering with 1. Pascal has arrays with user-defined indices. This makes it possible to model the array indices after the problem domain.


Fencepost error

A fencepost error (occasionally called a telegraph pole, lamp-post, or picket fence error) is a specific type of off-by-one error. An early description of this error appears in the works of
Vitruvius Vitruvius (; c. 80–70 BC – after c. 15 BC) was a Roman architect and engineer during the 1st century BC, known for his multi-volume work entitled ''De architectura''. He originated the idea that all buildings should have three attribute ...
. The following problem illustrates the error: The common answer of 10 posts is wrong. This response comes from dividing the length of the fence by the spacing apart from each post, with the quotient being erroneously classified as the number of posts. In actuality, the fence has 10 sections and 11 posts. In this scenario, a fence with ''n'' sections will have posts. Conversely, if the fence contains ''n'' posts, it will contain sections. This relationship is important to consider when dealing with the reverse error. The reverse error occurs when the number of posts is known and the number of sections is assumed to be the same. Depending on the design of the fence, this assumption can be correct or incorrect. The following problem demonstrates the reverse error: The interpretation for the fence's design changes the answer to this problem. The correct number of sections for a fence is if the fence is a free-standing line segment bounded by a post at each of its ends (e.g., a fence between two passageway gaps), ''n'' if the fence forms one complete, free-standing loop (e.g., enclosure accessible by surmounting, such as a boxing ring), or if posts do not occur at the ends of a line-segment-like fence (e.g., a fence between and wall-anchored to two buildings). The precise problem definition must be carefully considered, as the setup for one situation may give the wrong answer for other situations. Fencepost errors come from counting things rather than the spaces between them, or vice versa, or by neglecting to consider whether one should count one or both ends of a row. Fencepost errors can also occur in units other than length. For example, the
Time Pyramid The ''Zeitpyramide'' () is a work of public art by Manfred Laber under construction in Wemding, Germany. The pyramid, begun in 1993, at the 1,200th anniversary of Wemding, will take another years to complete and is scheduled to be finished in ...
, consisting of 120 blocks placed at 10-year intervals between blocks, is scheduled to take 1,190 years to build (not 1,200), from the installation of the first block to the last block. One of the earliest fencepost errors involved time, where the
Julian calendar The Julian calendar, proposed by Roman consul Julius Caesar in 46 BC, was a reform of the Roman calendar. It took effect on , by edict. It was designed with the aid of Greek mathematicians and astronomers such as Sosigenes of Alexandria. ...
originally calculated leap years incorrectly, due to counting inclusively rather than exclusively, yielding a leap year every three years rather than every four. "Fencepost error" can, in rare occasions, refer to an error induced by unexpected regularities in input values, which can (for instance) completely thwart a theoretically efficient
binary tree In computer science, a binary tree is a k-ary k = 2 tree data structure in which each node has at most two children, which are referred to as the ' and the '. A recursive definition using just set theory notions is that a (non-empty) binary tr ...
or
hash function A hash function is any function that can be used to map data of arbitrary size to fixed-size values. The values returned by a hash function are called ''hash values'', ''hash codes'', ''digests'', or simply ''hashes''. The values are usually ...
implementation. This error involves the difference between expected and worst case behaviours of an
algorithm In mathematics and computer science, an algorithm () is a finite sequence of rigorous instructions, typically used to solve a class of specific problems or to perform a computation. Algorithms are used as specifications for performing ...
. In larger numbers, being off by one is often not a major issue. In smaller numbers, however, and specific cases where accuracy is paramount committing an off-by-one error can be disastrous. Sometimes such an issue will also be repeated and, therefore, worsened, by someone passing on an incorrect calculation if the following person makes the same kind of mistake again (of course, the error might also be reversed). An example of this error can occur in the computational language
MATLAB MATLAB (an abbreviation of "MATrix LABoratory") is a proprietary multi-paradigm programming language and numeric computing environment developed by MathWorks. MATLAB allows matrix manipulations, plotting of functions and data, implementatio ...
with the linspace()
linear interpolation In mathematics, linear interpolation is a method of curve fitting using linear polynomials to construct new data points within the range of a discrete set of known data points. Linear interpolation between two known points If the two known poi ...
function, whose parameters are (''lower value'', ''upper value'', ''number of values'') and not (''lower value'', ''upper value'', ''number of increments''). A programmer who misunderstands the third parameter to be the number of increments might hope that linspace(0,10,5) would achieve a sequence but instead would get .


Security implications

A common off-by-one error which results in a security-related bug is caused by misuse of the
C standard library The C standard library or libc is the standard library for the C programming language, as specified in the ISO C standard.ISO/ IEC (2018). '' ISO/IEC 9899:2018(E): Programming Languages - C §7'' Starting from the original ANSI C standard, it was ...
strncat routine. A common misconception with strncat is that the guaranteed null termination will not write beyond the maximum length. In reality it will write a terminating null character one byte beyond the maximum length specified. The following code contains such a bug: void foo (char *s) Off-by-one errors are common in using the C library because it is not consistent with respect to whether one needs to subtract 1 byte – functions like fgets() and strncpy will never write past the length given them (fgets() subtracts 1 itself, and only retrieves (length − 1) bytes), whereas others, like strncat will write past the length given them. So the programmer has to remember for which functions they need to subtract 1. On some systems (
little endian In computing, endianness, also known as byte sex, is the order or sequence of bytes of a word of digital data in computer memory. Endianness is primarily expressed as big-endian (BE) or little-endian (LE). A big-endian system stores the most sig ...
architectures in particular) this can result in the overwriting of the least significant byte of the
frame pointer In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, program stack, control stack, run-time stack, or ma ...
. This can cause an exploitable condition where an attacker can hijack the local variables for the calling routine. One approach that often helps avoid such problems is to use variants of these functions that calculate how much to write based on the total length of the buffer, rather than the maximum number of characters to write. Such functions include strlcat and strlcpy, and are often considered "safer" because they make it easier to avoid accidentally writing past the end of a buffer. (In the code example above, calling strlcat(buf, s, sizeof(buf)) instead would remove the bug.)


See also

*
Boundary-value analysis Boundary-value analysis is a software testing technique in which tests are designed to include representatives of boundary values in a range. The idea comes from the boundary. Given that we have a set of test vectors to test the system, a topolog ...
*
Pigeonhole principle In mathematics, the pigeonhole principle states that if items are put into containers, with , then at least one container must contain more than one item. For example, if one has three gloves (and none is ambidextrous/reversible), then there m ...
*
Rounding error A roundoff error, also called rounding error, is the difference between the result produced by a given algorithm using exact arithmetic and the result produced by the same algorithm using finite-precision, rounded arithmetic. Rounding errors are d ...
*
Zero-based numbering Zero-based numbering is a way of numbering in which the initial element of a sequence is assigned the index 0, rather than the index 1 as is typical in everyday ''non-mathematical'' or ''non-programming'' circumstances. Under zero-based ...


References


Citations


Sources

* ''An earlier version of this article was based o
fencepost error
a
FOLDOC
used with permission.'' * * In the Common Weakness Enumeration system this issue is listed a
CWE-193: Off-by-one Error


Further reading

* {{DEFAULTSORT:Off-By-One Error Software bugs Computer security exploits Articles with example C code