mirror of
https://github.com/hohn/codeql-info.git
synced 2025-12-16 20:53:04 +01:00
325 lines
27 KiB
HTML
325 lines
27 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html lang="en" data-content_root="../">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
|
|
<title>Hash consing and value numbering — CodeQL</title>
|
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
|
|
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=93459777" />
|
|
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
|
|
<script src="../_static/doctools.js?v=888ff710"></script>
|
|
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
|
|
<link rel="icon" href="../_static/favicon.ico"/>
|
|
<link rel="index" title="Index" href="../genindex.html" />
|
|
<link rel="search" title="Search" href="../search.html" />
|
|
<link rel="next" title="CodeQL for C#" href="codeql-for-csharp.html" />
|
|
<link rel="prev" title="Using range analysis for C and C++" href="using-range-analsis-in-cpp.html" />
|
|
|
|
<title>CodeQL docs</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/primer.css" type="text/css" />
|
|
|
|
|
|
</head><body>
|
|
<header class="Header">
|
|
<div class="Header-item--full">
|
|
<a href="https://codeql.github.com/docs" class="Header-link f2 d-flex flex-items-center">
|
|
<!-- <%= octicon "mark-github", class: "mr-2", height: 32 %> -->
|
|
<svg height="32" class="octicon octicon-mark-github mr-2" viewBox="0 0 16 16" version="1.1" width="32"
|
|
aria-hidden="true">
|
|
<path fill-rule="evenodd"
|
|
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">
|
|
</path>
|
|
</svg>
|
|
<span class="hide-sm">CodeQL documentation</span>
|
|
</a>
|
|
</div>
|
|
<div class="Header-item hide-sm hide-md">
|
|
<script src="https://addsearch.com/js/?key=93b4d287e2fc079a4089412b669785d5&categories=!0xhelp.semmle.com,0xcodeql.github.com,1xdocs,1xcodeql-standard-libraries,1xcodeql-query-help"></script>
|
|
</div>
|
|
<div class="Header-item">
|
|
|
|
<details class="dropdown details-reset details-overlay d-inline-block">
|
|
<summary class="btn bg-gray-dark text-white border" aria-haspopup="true">
|
|
CodeQL resources
|
|
<div class="dropdown-caret"></div>
|
|
</summary>
|
|
|
|
<ul class="dropdown-menu dropdown-menu-se dropdown-menu-dark">
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-overview">CodeQL overview</a></li>
|
|
<li class="dropdown-divider" role="separator"></li>
|
|
<div class="dropdown-header">
|
|
CodeQL tools
|
|
</div>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-for-visual-studio-code">CodeQL for VS Code</a>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-cli">CodeQL CLI</a>
|
|
</li>
|
|
<li class="dropdown-divider" role="separator"></li>
|
|
<div class="dropdown-header">
|
|
CodeQL guides
|
|
</div>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/docs/writing-codeql-queries">Writing CodeQL queries</a></li>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-language-guides">CodeQL language guides</a>
|
|
<li class="dropdown-divider" role="separator"></li>
|
|
<div class="dropdown-header">
|
|
Reference docs
|
|
</div>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/docs/ql-language-reference/">QL language
|
|
reference</a>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-standard-libraries">CodeQL
|
|
standard-libraries</a>
|
|
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-query-help">CodeQL
|
|
query help</a>
|
|
<li class="dropdown-divider" role="separator"></li>
|
|
<div class="dropdown-header">
|
|
Source files
|
|
</div>
|
|
<li><a class="dropdown-item" href="https://github.com/github/codeql">CodeQL repository</a>
|
|
</ul>
|
|
</details>
|
|
|
|
</div>
|
|
|
|
</header>
|
|
<main class="bg-gray-light clearfix">
|
|
<nav class="SideNav position-sticky top-0 col-lg-3 col-md-3 float-left p-4 hide-sm hide-md overflow-y-auto">
|
|
|
|
<ul class="current">
|
|
<li class="toctree-l1"><a class="reference internal" href="../codeql-overview/index.html">CodeQL overview</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../codeql-for-visual-studio-code/index.html">CodeQL for Visual Studio Code</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../codeql-cli/index.html">CodeQL CLI</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../writing-codeql-queries/index.html">Writing CodeQL queries</a></li>
|
|
<li class="toctree-l1 current"><a class="reference internal" href="index.html">CodeQL language guides</a><ul class="current">
|
|
<li class="toctree-l2 current"><a class="reference internal" href="codeql-for-cpp.html">CodeQL for C and C++</a><ul class="current">
|
|
<li class="toctree-l3"><a class="reference internal" href="basic-query-for-cpp-code.html">Basic query for C and C++ code</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="codeql-library-for-cpp.html">CodeQL library for C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="functions-in-cpp.html">Functions in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="expressions-types-and-statements-in-cpp.html">Expressions, types, and statements in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="conversions-and-classes-in-cpp.html">Conversions and classes in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="analyzing-data-flow-in-cpp.html">Analyzing data flow in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="refining-a-query-to-account-for-edge-cases.html">Refining a query to account for edge cases</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="detecting-a-potential-buffer-overflow.html">Detecting a potential buffer overflow</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="using-the-guards-library-in-cpp.html">Using the guards library in C and C++</a></li>
|
|
<li class="toctree-l3"><a class="reference internal" href="using-range-analsis-in-cpp.html">Using range analysis for C and C++</a></li>
|
|
<li class="toctree-l3 current"><a class="current reference internal" href="#">Hash consing and value numbering</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-csharp.html">CodeQL for C#</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-go.html">CodeQL for Go</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-java.html">CodeQL for Java</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-javascript.html">CodeQL for JavaScript</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-python.html">CodeQL for Python</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="codeql-for-ruby.html">CodeQL for Ruby</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../ql-language-reference/index.html">QL language reference</a></li>
|
|
</ul>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
<div class="body col-sm-12 col-md-9 col-lg-9 float-left border-left">
|
|
|
|
<div class="hide-lg hide-xl px-4 pt-4">
|
|
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<ul>
|
|
<li class="nav-item nav-item-0"><a href="../contents.html">CodeQL</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="index.html"
|
|
>CodeQL language guides</a> »</li>
|
|
<li class="nav-item nav-item-2"><a href="codeql-for-cpp.html"
|
|
accesskey="U">CodeQL for C and C++</a> »</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<article class="p-4 col-lg-10 col-md-10 col-sm-12">
|
|
|
|
<section id="hash-consing-and-value-numbering">
|
|
<span id="id1"></span><h1>Hash consing and value numbering<a class="headerlink" href="#hash-consing-and-value-numbering" title="Link to this heading">¶</a></h1>
|
|
<p>You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases.</p>
|
|
<section id="about-the-hash-consing-and-value-numbering-libraries">
|
|
<h2>About the hash consing and value numbering libraries<a class="headerlink" href="#about-the-hash-consing-and-value-numbering-libraries" title="Link to this heading">¶</a></h2>
|
|
<p>In C and C++ databases, each node in the abstract syntax tree is represented by a separate object. This allows both analysis and results display to refer to specific appearances of a piece of syntax. However, it is frequently useful to determine whether two expressions are equivalent, either syntactically or semantically.</p>
|
|
<p>The hash consing library (defined in <code class="docutils literal notranslate"><span class="pre">semmle.code.cpp.valuenumbering.HashCons</span></code>) provides a mechanism for identifying expressions that have the same syntactic structure. The global value numbering library (defined in <code class="docutils literal notranslate"><span class="pre">semmle.code.cpp.valuenumbering.GlobalValueNumbering</span></code>) provides a mechanism for identifying expressions that compute the same value at runtime. Both libraries partition the expressions in each function into equivalence classes represented by objects. Each <code class="docutils literal notranslate"><span class="pre">HashCons</span></code> object represents a set of expressions with identical parse trees, while <code class="docutils literal notranslate"><span class="pre">GVN</span></code> objects represent sets of expressions that will always compute the same value. For more information, see <a class="reference external" href="https://en.wikipedia.org/wiki/Hash_consing">Hash consing</a> and <a class="reference external" href="https://en.wikipedia.org/wiki/Value_numbering">Value numbering</a> on Wikipedia.</p>
|
|
</section>
|
|
<section id="example-c-code">
|
|
<h2>Example C code<a class="headerlink" href="#example-c-code" title="Link to this heading">¶</a></h2>
|
|
<p>In the following C program, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+</span> <span class="pre">y</span></code> and <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+</span> <span class="pre">z</span></code> will be assigned the same value number but different hash conses.</p>
|
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
|
|
<span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
|
|
<span class="kt">int</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
|
|
<span class="k">if</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">z</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
|
<span class="w"> </span><span class="p">...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>However, in the next example, the uses of <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+</span> <span class="pre">y</span></code> will have different value numbers but the same hash cons.</p>
|
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
|
|
<span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
|
|
<span class="k">if</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
|
<span class="w"> </span><span class="p">...</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
|
|
|
|
<span class="k">if</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
|
<span class="w"> </span><span class="p">...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</section>
|
|
<section id="value-numbering">
|
|
<h2>Value numbering<a class="headerlink" href="#value-numbering" title="Link to this heading">¶</a></h2>
|
|
<p>The value numbering library (defined in <code class="docutils literal notranslate"><span class="pre">semmle.code.cpp.valuenumbering.GlobalValueNumbering</span></code>) provides a mechanism for identifying expressions that compute the same value at runtime. Value numbering is useful when your primary concern is with the values being produced or the eventual machine code being run. For instance, value numbering might be used to determine whether a check is being done against the same value as the operation it is guarding.</p>
|
|
<section id="the-value-numbering-api">
|
|
<h3>The value numbering API<a class="headerlink" href="#the-value-numbering-api" title="Link to this heading">¶</a></h3>
|
|
<p>The value numbering library exposes its interface primarily through the <code class="docutils literal notranslate"><span class="pre">GVN</span></code> class. Each instance of <code class="docutils literal notranslate"><span class="pre">GVN</span></code> represents a set of expressions that will always evaluate to the same value. To get an expression in the set represented by a particular <code class="docutils literal notranslate"><span class="pre">GVN</span></code>, use the <code class="docutils literal notranslate"><span class="pre">getAnExpr()</span></code> member predicate.</p>
|
|
<p>To get the <code class="docutils literal notranslate"><span class="pre">GVN</span></code> of an <code class="docutils literal notranslate"><span class="pre">Expr</span></code>, use the <code class="docutils literal notranslate"><span class="pre">globalValueNumber</span></code> predicate.</p>
|
|
<blockquote class="pull-quote">
|
|
<div><p>Note</p>
|
|
<p>While the <code class="docutils literal notranslate"><span class="pre">GVN</span></code> class has <code class="docutils literal notranslate"><span class="pre">toString</span></code> and <code class="docutils literal notranslate"><span class="pre">getLocation</span></code> methods, these are only provided as debugging aids. They give the <code class="docutils literal notranslate"><span class="pre">toString</span></code> and <code class="docutils literal notranslate"><span class="pre">getLocation</span></code> of an arbitrary <code class="docutils literal notranslate"><span class="pre">Expr</span></code> within the set.</p>
|
|
</div></blockquote>
|
|
</section>
|
|
<section id="why-not-a-predicate">
|
|
<h3>Why not a predicate?<a class="headerlink" href="#why-not-a-predicate" title="Link to this heading">¶</a></h3>
|
|
<p>The obvious interface for this library would be a predicate <code class="docutils literal notranslate"><span class="pre">equivalent(Expr</span> <span class="pre">e1,</span> <span class="pre">Expr</span> <span class="pre">e2)</span></code>. However, this predicate would be very large, with a quadratic number of rows for each set of equivalent expressions. By using a class as an intermediate step, the number of rows can be kept linear, and therefore can be cached.</p>
|
|
</section>
|
|
<section id="example-query">
|
|
<h3>Example query<a class="headerlink" href="#example-query" title="Link to this heading">¶</a></h3>
|
|
<p>This query uses the <code class="docutils literal notranslate"><span class="pre">GVN</span></code> class to identify calls to <code class="docutils literal notranslate"><span class="pre">strncpy</span></code> where the size argument is derived from the source rather than the destination</p>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>from FunctionCall strncpy, FunctionCall strlen
|
|
where
|
|
strncpy.getTarget().hasGlobalName("strncpy") and
|
|
strlen.getTarget().hasGlobalName("strlen") and
|
|
globalValueNumber(strncpy.getArgument(1)) = globalValueNumber(strlen.getArgument(0)) and
|
|
strlen = strncpy.getArgument(2)
|
|
select ci, "This call to strncpy is bounded by the size of the source rather than the destination"
|
|
</pre></div>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
<section id="hash-consing">
|
|
<h2>Hash consing<a class="headerlink" href="#hash-consing" title="Link to this heading">¶</a></h2>
|
|
<p>The hash consing library (defined in <code class="docutils literal notranslate"><span class="pre">semmle.code.cpp.valuenumbering.HashCons</span></code>) provides a mechanism for identifying expressions that have the same syntactic structure. Hash consing is useful when your primary concern is with the text of the code. For instance, hash consing might be used to detect duplicate code within a function.</p>
|
|
<section id="the-hash-consing-api">
|
|
<h3>The hash consing API<a class="headerlink" href="#the-hash-consing-api" title="Link to this heading">¶</a></h3>
|
|
<p>The hash consing library exposes its interface primarily through the <code class="docutils literal notranslate"><span class="pre">HashCons</span></code> class. Each instance of <code class="docutils literal notranslate"><span class="pre">HashCons</span></code> represents a set of expressions within one function that have the same syntax (including referring to the same variables). To get an expression in the set represented by a particular <code class="docutils literal notranslate"><span class="pre">HashCons</span></code>, use the <code class="docutils literal notranslate"><span class="pre">getAnExpr()</span></code> member predicate.</p>
|
|
<blockquote class="pull-quote">
|
|
<div><p>Note</p>
|
|
<p>While the <code class="docutils literal notranslate"><span class="pre">HashCons</span></code> class has <code class="docutils literal notranslate"><span class="pre">toString</span></code> and <code class="docutils literal notranslate"><span class="pre">getLocation</span></code> methods, these are only provided as debugging aids. They give the <code class="docutils literal notranslate"><span class="pre">toString</span></code> and <code class="docutils literal notranslate"><span class="pre">getLocation</span></code> of an arbitrary <code class="docutils literal notranslate"><span class="pre">Expr</span></code> within the set.</p>
|
|
</div></blockquote>
|
|
<p>To get the <code class="docutils literal notranslate"><span class="pre">HashCons</span></code> of an <code class="docutils literal notranslate"><span class="pre">Expr</span></code>, use the <code class="docutils literal notranslate"><span class="pre">hashCons</span></code> predicate.</p>
|
|
</section>
|
|
<section id="id2">
|
|
<h3>Example query<a class="headerlink" href="#id2" title="Link to this heading">¶</a></h3>
|
|
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import cpp
|
|
import semmle.code.cpp.valuenumbering.HashCons
|
|
|
|
from IfStmt outer, IfStmt inner
|
|
where
|
|
outer.getElse+() = inner and
|
|
hashCons(outer.getCondition()) = hashCons(inner.getCondition())
|
|
select inner.getCondition(), "The condition of this if statement duplicates the condition of $@",
|
|
outer.getCondition(), "an enclosing if statement"
|
|
</pre></div>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
<section id="further-reading">
|
|
<h2>Further reading<a class="headerlink" href="#further-reading" title="Link to this heading">¶</a></h2>
|
|
<ul class="simple">
|
|
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/cpp/ql/src">CodeQL queries for C and C++</a></p></li>
|
|
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/cpp/ql/examples">Example queries for C and C++</a></p></li>
|
|
<li><p><a class="reference external" href="https://codeql.github.com/codeql-standard-libraries/cpp/">CodeQL library reference for C and C++</a></p></li>
|
|
</ul>
|
|
<ul class="simple">
|
|
<li><p>“<a class="reference internal" href="../ql-language-reference/index.html#ql-language-reference"><span class="std std-ref">QL language reference</span></a>”</p></li>
|
|
<li><p>“<a class="reference internal" href="../codeql-overview/codeql-tools.html#codeql-tools"><span class="std std-ref">CodeQL tools</span></a>”</p></li>
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
|
|
|
|
</article>
|
|
|
|
<!-- GitHub footer, with links to terms and privacy statement -->
|
|
<div class="px-3 px-md-6 f6 py-4 d-sm-flex flex-justify-between flex-row-reverse flex-items-center border-top">
|
|
<ul class="list-style-none d-flex flex-items-center mb-3 mb-sm-0 lh-condensed-ultra">
|
|
<li class="mr-3">
|
|
<a href="https://twitter.com/github" title="GitHub on Twitter" style="color: #959da5;">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 273.5 222.3" class="d-block" height="18">
|
|
<path
|
|
d="M273.5 26.3a109.77 109.77 0 0 1-32.2 8.8 56.07 56.07 0 0 0 24.7-31 113.39 113.39 0 0 1-35.7 13.6 56.1 56.1 0 0 0-97 38.4 54 54 0 0 0 1.5 12.8A159.68 159.68 0 0 1 19.1 10.3a56.12 56.12 0 0 0 17.4 74.9 56.06 56.06 0 0 1-25.4-7v.7a56.11 56.11 0 0 0 45 55 55.65 55.65 0 0 1-14.8 2 62.39 62.39 0 0 1-10.6-1 56.24 56.24 0 0 0 52.4 39 112.87 112.87 0 0 1-69.7 24 119 119 0 0 1-13.4-.8 158.83 158.83 0 0 0 86 25.2c103.2 0 159.6-85.5 159.6-159.6 0-2.4-.1-4.9-.2-7.3a114.25 114.25 0 0 0 28.1-29.1"
|
|
fill="currentColor"></path>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
<li class="mr-3">
|
|
<a href="https://www.facebook.com/GitHub" title="GitHub on Facebook" style="color: #959da5;">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.3 15.4" class="d-block" height="18">
|
|
<path
|
|
d="M14.5 0H.8a.88.88 0 0 0-.8.9v13.6a.88.88 0 0 0 .8.9h7.3v-6h-2V7.1h2V5.4a2.87 2.87 0 0 1 2.5-3.1h.5a10.87 10.87 0 0 1 1.8.1v2.1h-1.3c-1 0-1.1.5-1.1 1.1v1.5h2.3l-.3 2.3h-2v5.9h3.9a.88.88 0 0 0 .9-.8V.8a.86.86 0 0 0-.8-.8z"
|
|
fill="currentColor"></path>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
<li class="mr-3">
|
|
<a href="https://www.youtube.com/github" title="GitHub on YouTube" style="color: #959da5;">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.17 13.6" class="d-block" height="16">
|
|
<path
|
|
d="M18.77 2.13A2.4 2.4 0 0 0 17.09.42C15.59 0 9.58 0 9.58 0a57.55 57.55 0 0 0-7.5.4A2.49 2.49 0 0 0 .39 2.13 26.27 26.27 0 0 0 0 6.8a26.15 26.15 0 0 0 .39 4.67 2.43 2.43 0 0 0 1.69 1.71c1.52.42 7.5.42 7.5.42a57.69 57.69 0 0 0 7.51-.4 2.4 2.4 0 0 0 1.68-1.71 25.63 25.63 0 0 0 .4-4.67 24 24 0 0 0-.4-4.69zM7.67 9.71V3.89l5 2.91z"
|
|
fill="currentColor"></path>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
<li class="mr-3 flex-self-start">
|
|
<a href="https://www.linkedin.com/company/github" title="GitHub on Linkedin" style="color: #959da5;">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19 18" class="d-block" height="18">
|
|
<path
|
|
d="M3.94 2A2 2 0 1 1 2 0a2 2 0 0 1 1.94 2zM4 5.48H0V18h4zm6.32 0H6.34V18h3.94v-6.57c0-3.66 4.77-4 4.77 0V18H19v-7.93c0-6.17-7.06-5.94-8.72-2.91z"
|
|
fill="currentColor"></path>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://github.com/github" title="GitHub's organization" style="color: #959da5;">
|
|
<svg version="1.1" width="20" height="20" viewBox="0 0 16 16" class="octicon octicon-mark-github"
|
|
aria-hidden="true">
|
|
<path fill-rule="evenodd"
|
|
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
|
|
</path>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<ul class="list-style-none d-flex text-gray">
|
|
<li class="mr-3">©
|
|
<script type="text/javascript">document.write(new Date().getFullYear());</script> GitHub, Inc.</li>
|
|
<li class="mr-3"><a
|
|
href="https://docs.github.com/github/site-policy/github-terms-of-service"
|
|
class="link-gray">Terms </a></li>
|
|
<li><a href="https://docs.github.com/github/site-policy/github-privacy-statement"
|
|
class="link-gray">Privacy </a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<script type="text/javascript">
|
|
$(document).ready(function () {
|
|
$(".toggle > *").hide();
|
|
$(".toggle .name").show();
|
|
$(".toggle .name").click(function () {
|
|
$(this).parent().children().not(".name").toggle(400);
|
|
$(this).parent().children(".name").toggleClass("open");
|
|
})
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html> |