mirror of
https://github.com/hohn/codeql-info.git
synced 2025-12-16 20:53:04 +01:00
309 lines
23 KiB
HTML
309 lines
23 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>Debugging data-flow queries using partial flow — 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="QL tutorials" href="ql-tutorials.html" />
|
||
<link rel="prev" title="Troubleshooting query performance" href="troubleshooting-query-performance.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 current"><a class="reference internal" href="index.html">Writing CodeQL queries</a><ul class="current">
|
||
<li class="toctree-l2 current"><a class="reference internal" href="codeql-queries.html">CodeQL queries</a><ul class="current">
|
||
<li class="toctree-l3"><a class="reference internal" href="about-codeql-queries.html">About CodeQL queries</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="metadata-for-codeql-queries.html">Metadata for CodeQL queries</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="query-help-files.html">Query help files</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="defining-the-results-of-a-query.html">Defining the results of a query</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="providing-locations-in-codeql-queries.html">Providing locations in CodeQL queries</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="about-data-flow-analysis.html">About data flow analysis</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="creating-path-queries.html">Creating path queries</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="troubleshooting-query-performance.html">Troubleshooting query performance</a></li>
|
||
<li class="toctree-l3 current"><a class="current reference internal" href="#">Debugging data-flow queries using partial flow</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="toctree-l2"><a class="reference internal" href="ql-tutorials.html">QL tutorials</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../codeql-language-guides/index.html">CodeQL language guides</a></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"
|
||
>Writing CodeQL queries</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="codeql-queries.html"
|
||
accesskey="U">CodeQL queries</a> »</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<article class="p-4 col-lg-10 col-md-10 col-sm-12">
|
||
|
||
<section id="debugging-data-flow-queries-using-partial-flow">
|
||
<span id="id1"></span><h1>Debugging data-flow queries using partial flow<a class="headerlink" href="#debugging-data-flow-queries-using-partial-flow" title="Link to this heading">¶</a></h1>
|
||
<p>If a data-flow query doesn’t produce the results you expect to see, you can use partial flow to debug the problem.</p>
|
||
<p>In CodeQL, you can use <a class="reference internal" href="about-data-flow-analysis.html#about-data-flow-analysis"><span class="std std-ref">data flow analysis</span></a> to compute the possible values that a variable can hold at various points in a program.
|
||
A typical data-flow query looks like this:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>class MyConfig extends TaintTracking::Configuration {
|
||
MyConfig() { this = "MyConfig" }
|
||
|
||
override predicate isSource(DataFlow::Node node) { node instanceof MySource }
|
||
|
||
override predicate isSink(DataFlow::Node node) { node instanceof MySink }
|
||
}
|
||
|
||
from MyConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||
where config.hasFlowPath(source, sink)
|
||
select sink.getNode(), source, sink, "Sink is reached from $@.", source.getNode(), "here"
|
||
</pre></div>
|
||
</div>
|
||
<p>The same query can be slightly simplified by rewriting it without <a class="reference internal" href="creating-path-queries.html#creating-path-queries"><span class="std std-ref">path explanations</span></a>:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>from MyConfig config, DataFlow::Node source, DataFlow::Node sink
|
||
where config.hasPath(source, sink)
|
||
select sink, "Sink is reached from $@.", source.getNode(), "here"
|
||
</pre></div>
|
||
</div>
|
||
<p>If a data-flow query that you have written doesn’t produce the results you expect it to, there may be a problem with your query.
|
||
You can try to debug the potential problem by following the steps described below.</p>
|
||
<section id="checking-sources-and-sinks">
|
||
<h2>Checking sources and sinks<a class="headerlink" href="#checking-sources-and-sinks" title="Link to this heading">¶</a></h2>
|
||
<p>Initially, you should make sure that the source and sink definitions contain what you expect. If either the source or sink is empty then there can never be any data flow. The easiest way to check this is using quick evaluation in CodeQL for VS Code. Select the text <code class="docutils literal notranslate"><span class="pre">node</span> <span class="pre">instanceof</span> <span class="pre">MySource</span></code>, right-click, and choose “CodeQL: Quick Evaluation”. This will evaluate the highlighted text, which in this case means the set of sources. For more information, see <a class="reference internal" href="../codeql-for-visual-studio-code/analyzing-your-projects.html#running-a-specific-part-of-a-query-or-library"><span class="std std-ref">Analyzing your projects</span></a> in the CodeQL for VS Code help.</p>
|
||
<p>If both source and sink definitions look good then we will need to look for missing flow steps.</p>
|
||
</section>
|
||
<section id="fieldflowbranchlimit">
|
||
<h2><code class="docutils literal notranslate"><span class="pre">fieldFlowBranchLimit</span></code><a class="headerlink" href="#fieldflowbranchlimit" title="Link to this heading">¶</a></h2>
|
||
<p>Data-flow configurations contain a parameter called <code class="docutils literal notranslate"><span class="pre">fieldFlowBranchLimit</span></code>. If the value is set too high, you may experience performance degradation, but if it’s too low you may miss results. When debugging data flow try setting <code class="docutils literal notranslate"><span class="pre">fieldFlowBranchLimit</span></code> to a high value and see whether your query generates more results. For example, try adding the following to your configuration:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>override int fieldFlowBranchLimit() { result = 5000 }
|
||
</pre></div>
|
||
</div>
|
||
<p>If there are still no results and performance is still useable, then it is best to leave this set to a high value while doing further debugging.</p>
|
||
</section>
|
||
<section id="partial-flow">
|
||
<h2>Partial flow<a class="headerlink" href="#partial-flow" title="Link to this heading">¶</a></h2>
|
||
<p>A naive next step could be to change the sink definition to <code class="docutils literal notranslate"><span class="pre">any()</span></code>. This would mean that we would get a lot of flow to all the places that are reachable from the sources. While this approach may work in some cases, you might find that it produces so many results that it’s very hard to explore the findings. It can also dramatically affect query performance. More importantly, you might not even see all the partial flow paths. This is because the data-flow library tries very hard to prune impossible paths and, since field stores and reads must be evenly matched along a path, we will never see paths going through a store that fail to reach a corresponding read. This can make it hard to see where flow actually stops.</p>
|
||
<p>To avoid these problems, a data-flow <code class="docutils literal notranslate"><span class="pre">Configuration</span></code> comes with a mechanism for exploring partial flow that tries to deal with these caveats. This is the <code class="docutils literal notranslate"><span class="pre">Configuration.hasPartialFlow</span></code> predicate:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>/**
|
||
* Holds if there is a partial data flow path from `source` to `node`. The
|
||
* approximate distance between `node` and the closest source is `dist` and
|
||
* is restricted to be less than or equal to `explorationLimit()`. This
|
||
* predicate completely disregards sink definitions.
|
||
*
|
||
* This predicate is intended for dataflow exploration and debugging and may
|
||
* perform poorly if the number of sources is too big and/or the exploration
|
||
* limit is set too high without using barriers.
|
||
*
|
||
* This predicate is disabled (has no results) by default. Override
|
||
* `explorationLimit()` with a suitable number to enable this predicate.
|
||
*
|
||
* To use this in a `path-problem` query, import the module `PartialPathGraph`.
|
||
*/
|
||
final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) {
|
||
</pre></div>
|
||
</div>
|
||
<p>There is also a <code class="docutils literal notranslate"><span class="pre">Configuration.hasPartialFlowRev</span></code> for exploring flow backwards from a sink.</p>
|
||
<p>As noted in the documentation for <code class="docutils literal notranslate"><span class="pre">hasPartialFlow</span></code> (for example, in the
|
||
<a class="reference external" href="https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/dataflow/internal/DataFlowImpl2.qll/predicate.DataFlowImpl2$Configuration$hasPartialFlow.3.html">CodeQL for Java documentation</a>) you must first enable this by adding an override of <code class="docutils literal notranslate"><span class="pre">explorationLimit</span></code>. For example:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>override int explorationLimit() { result = 5 }
|
||
</pre></div>
|
||
</div>
|
||
<p>This defines the exploration radius within which <code class="docutils literal notranslate"><span class="pre">hasPartialFlow</span></code> returns results.</p>
|
||
<p>To get good performance when using <code class="docutils literal notranslate"><span class="pre">hasPartialFlow</span></code> it is important to ensure the <code class="docutils literal notranslate"><span class="pre">isSink</span></code> predicate of the configuration has no results. Likewise, when using <code class="docutils literal notranslate"><span class="pre">hasPartialFlowRev</span></code> the <code class="docutils literal notranslate"><span class="pre">isSource</span></code> predicate of the configuration should have no results.</p>
|
||
<p>It is also useful to focus on a single source at a time as the starting point for the flow exploration. This is most easily done by adding a temporary restriction in the <code class="docutils literal notranslate"><span class="pre">isSource</span></code> predicate.</p>
|
||
<p>To do quick evaluations of partial flow it is often easiest to add a predicate to the query that is solely intended for quick evaluation (right-click the predicate name and choose “CodeQL: Quick Evaluation”). A good starting point is something like:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>predicate adhocPartialFlow(Callable c, PartialPathNode n, Node src, int dist) {
|
||
exists(MyConfig conf, PartialPathNode source |
|
||
conf.hasPartialFlow(source, n, dist) and
|
||
src = source.getNode() and
|
||
c = n.getNode().getEnclosingCallable()
|
||
)
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
<p>If you are focusing on a single source then the <code class="docutils literal notranslate"><span class="pre">src</span></code> column is superfluous. You may of course also add other columns of interest based on <code class="docutils literal notranslate"><span class="pre">n</span></code>, but including the enclosing callable and the distance to the source at the very least is generally recommended, as they can be useful columns to sort on to better inspect the results.</p>
|
||
<p>If you see a large number of partial flow results, you can focus them in a couple of ways:</p>
|
||
<ul class="simple">
|
||
<li><p>If flow travels a long distance following an expected path, that can result in a lot of uninteresting flow being included in the exploration radius. To reduce the amount of uninteresting flow, you can replace the source definition with a suitable <code class="docutils literal notranslate"><span class="pre">node</span></code> that appears along the path and restart the partial flow exploration from that point.</p></li>
|
||
<li><p>Creative use of barriers and sanitizers can be used to cut off flow paths that are uninteresting. This also reduces the number of partial flow results to explore while debugging.</p></li>
|
||
</ul>
|
||
</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 internal" href="about-data-flow-analysis.html#about-data-flow-analysis"><span class="std std-ref">About data flow analysis</span></a></p></li>
|
||
<li><p><a class="reference internal" href="creating-path-queries.html#creating-path-queries"><span class="std std-ref">Creating path queries</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> |