Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Unreachable code
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{Short description|Section of code in a program that can never be executed}} In [[computer programming]], '''unreachable code''' is part of the [[source code]] of a program which can never be executed because there exists no [[control flow]] path to the code from the rest of the program.<ref>{{cite journal|last1=Debray|first1=Saumya K.|last2=Evans|first2=William|last3=Muth|first3=Robert|last4=De Sutter|first4=Bjorn|title=Compiler techniques for code compaction|journal=ACM Transactions on Programming Languages and Systems|date=1 March 2000|volume=22|issue=2|pages=378–415|doi=10.1145/349214.349233|citeseerx=10.1.1.43.7215|s2cid=6129772}}</ref> Unreachable code is sometimes also called ''dead code'',<ref>{{cite book | title = RTCA/DO-178C Software Considerations in Airborne Systems and Equipment Certification | publisher = [[Radio Technical Commission for Aeronautics|RTCA, Inc.]] | year = 2011 | url = https://my.rtca.org/NC__Product?id=a1B36000001IcmqEAC | page = 112 | quote = Dead code – Executable Object Code (or data) which exists as a result of a software development error but cannot be executed (code) or used (data) in any operational configuration of the target computer environment. It is not traceable to a system or software requirement. The following exceptions are often mistakenly categorized as dead code but are necessary for implementation of the requirements/design: embedded identifiers, defensive programming structures to improve robustness, and deactivated code such as unused library functions. [Since requirements-based review should identified such code as untraceable to functional requirements, static code analysis should identify such code as unreachable, and structural coverage analysis of requirements-based testing results should identify such code as unreachable, presence of unjustified dead code in a project should raise consideration of the effectiveness of the organization’s development and verification processes.] |access-date = 2019-06-11 }}</ref><ref>{{cite web |author= Jay Thomas |title= Requirements Traceability Forms the Foundation for Thorough Software Testing |date= 24 January 2017 |quote= The combination of requirements traceability with coverage analysis can also turn up areas of “dead code,” or code that’s never executed. This code can mostly be an inconvenience, but it can also be a security threat if a hacker can gain access and from there gain control. It’s code that can’t be traced and should therefore be eliminated. |url= https://ldra.com/requirements-traceability-forms-foundation-thorough-software-testing/ |access-date = 2019-06-11 }}</ref> although [[dead code]] may also refer to code that is executed but has no effect on the output of a program.<ref>{{cite book |author= MISRA Consortium |title= MISRA C:2012 Guidelines for the used of C language in critical systems |date= March 2013 |publisher= [[MIRA Ltd.|MIRA Limited]] |url= https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx |page= 41 |quote= Rule 2.2 there shall be no ''dead code''. Any operation that is executed but whose removal would not affect program behavior constitutes ''dead code''. |access-date = 2019-06-11 }}</ref> Unreachable code is generally considered undesirable for several reasons: * It uses memory unnecessarily * It can cause unnecessary use of the CPU's [[instruction cache]] ** This can also decrease [[data locality]] * Time and effort may be spent testing, maintaining and documenting code which is never used ** Sometimes an automated test is the only thing using the code. Unreachable code can have some legitimate uses, like providing a library of functions for calling or jumping to manually via a [[debugger]] while the program is halted after a [[breakpoint]]. This is particularly useful for examining and pretty-printing the internal state of the program. It may make sense to have such code in the shipped product, so that a developer can attach a debugger to a client's running instance. ==Causes== Unreachable code can exist for many reasons, such as: * programming errors in complex conditional branches * a consequence of the internal transformations performed by an [[optimizing compiler]]; * incomplete testing of new or modified code * Legacy code ** Code superseded by another implementation ** Unreachable code that a programmer decided not to delete because it is mingled with reachable code ** Potentially reachable code that current use cases never need ** Dormant code that is kept intentionally in case it is needed later * Code used only for debugging. Legacy code is that which was once useful but is no longer used or required. But unreachable code may also be part of a complex library, module or routine where it is useful to others or under conditions which are not met in a particular scenario. An example of such a conditionally unreachable code may be the implementation of a general string formatting function in a compiler's runtime library, which contains complex code to process all possible arguments, of which only a small subset is actually used. Compilers will typically not be able to remove the unused code sections at compile time, as the behavior is largely determined by the values of arguments at run time. ==Examples== In this fragment of C code: <syntaxhighlight lang="C"> int foo (int X, int Y) { return X + Y; int Z = X * Y; } </syntaxhighlight> the definition {{mono|int Z {{=}} X * Y;}} is never reached as the function always returns before it. Therefore, the {{mono|Z}} need be neither allocated storage nor initialized. ===goto fail bug=== <!-- Courtesy note per [[WP:RSECT]]: [[goto fail]] links here --> Apple's [[Transport Layer Security|SSL/TLS]] from February 2014 contained a major security flaw known formally as {{CVE|2014-1266}} and informally as the "goto fail bug".<ref name="gotofail">{{cite web|author=Adam Langley|year=2014|title=Apple's SSL/TLS bug|url=https://www.imperialviolet.org/2014/02/22/applebug.html}}</ref><ref name="gotofail_lessons">{{cite web|author=Arie van Deursen|year=2014|title=Learning from Apple's #gotofail Security Bug|url=http://avandeursen.com/2014/02/22/gotofail-security/}}</ref> The relevant code fragment<ref>{{cite web|title=sslKeyExchange.c - Source code for support for key exchange and server key exchange|url=http://opensource.apple.com/source/Security/Security-55471/libsecurity_ssl/lib/sslKeyExchange.c?txt}}</ref> is: <syntaxhighlight lang="c" highlight="12"> static OSStatus SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams, uint8_t *signature, UInt16 signatureLen) { OSStatus err; ... if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; ... fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; } </syntaxhighlight> Here, there are two successive <code>goto fail</code> statements. In the syntax of the C language, the second is unconditional, and hence ''always'' skips the call to <code>SSLHashSHA1.final</code>. As a consequence, <code>err</code> will hold the status of the SHA1 update operation, and signature verification will ''never'' fail.<ref name=gotofail/> Here, the unreachable code is the call to the <code>final</code> function.<ref name=gotofail_lessons/> Applying the [[Clang]] compiler with the option <code>-Weverything</code> includes unreachable code analysis, which would trigger an alarm for this code.<ref name=gotofail_lessons/> ===C++=== In [[C++]], some constructs are specified to have [[undefined behavior]]. A compiler is free to implement any behavior or none, and typically an optimizing compiler will assume the code is unreachable.<ref>{{cite web|url=https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior|publisher=Carnegie Mellon University|title=MSC15-C. Do not depend on undefined behavior|quote=Because compilers are not obligated to generate code for undefined behavior, these behaviors are candidates for optimization.|year=2020|access-date=28 September 2020}}</ref> ==Analysis== Detection of unreachable code is a form of [[control flow analysis]] to find code that can never be reached in any possible program state. In some languages (e.g. [[Java (programming language)|Java]]<ref>{{cite web|title=Java Language Specification|url=http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21}}</ref>) some forms of unreachable code are explicitly disallowed. The optimization that removes unreachable code is known as [[dead code elimination]]. Code may become unreachable as a consequence of transformations performed by an [[optimizing compiler]] (e.g., [[common subexpression elimination]]). In practice the sophistication of the analysis has a significant impact on the amount of unreachable code that is detected. For example, [[constant folding]] and simple flow analysis shows that the inside of the if-statement in the following code is unreachable: <syntaxhighlight lang="C"> int N = 2 + 1; if (N == 4) { /* unreachable */ } </syntaxhighlight> However, a great deal more sophistication is needed to work out that the corresponding block is unreachable in the following code: <syntaxhighlight lang="C"> double X = sqrt(2); if (X > 5) { /* unreachable */ } </syntaxhighlight> Unreachable code elimination technique is in the same class of optimizations as [[dead code elimination]] and [[redundant code]] elimination. ===Unreachability vs. profiling=== In some cases, a practical approach may be a combination of simple unreachability criteria and use of a [[Profiler (computer science)|profiler]] to handle the more complex cases. Profiling in general can not ''prove'' anything about the unreachability of a piece of code, but may be a good [[heuristic]] for finding potentially unreachable code. Once a suspect piece of code is found, other methods, such as a more powerful code analysis tool, or even analysis by hand, could be used to decide whether the code is truly unreachable. ==See also== *[[Code coverage]] *[[Redundant code]] *[[Dead code]] *[[Oxbow code]] *[[Halting problem]] – the general problem of determining whether a piece of code is unreachable is at least as hard as the halting problem and hence [[undecidable problem|undecidable]] ==References== {{reflist}} * <cite>Appel, A. W. 1998 Modern Compiler Implementation in Java. Cambridge University Press. </cite> * <cite>Muchnick S. S. 1997 Advanced Compiler Design and Implementation. Morgan Kaufmann. </cite> [[Category:Compiler optimizations]] [[Category:Software anomalies]] [[Category:Source code]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:CVE
(
edit
)
Template:Cite book
(
edit
)
Template:Cite journal
(
edit
)
Template:Cite web
(
edit
)
Template:Mono
(
edit
)
Template:Reflist
(
edit
)
Template:Short description
(
edit
)