Skip to content

Commit efa2647

Browse files
committed
Merge branch 'main' into calumgrant/qlql
2 parents dde18de + b993b5e commit efa2647

File tree

6 files changed

+202
-6
lines changed

6 files changed

+202
-6
lines changed

javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: codeql/javascript-experimental-atm-lib
22
description: CodeQL libraries for the experimental ML-powered queries
3-
version: 0.4.8
3+
version: 0.4.9
44
extractor: javascript
55
library: true
66
groups:

javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: codeql/javascript-experimental-atm-queries
22
description: Experimental ML-powered queries for JavaScript
33
language: javascript
4-
version: 0.4.8
4+
version: 0.4.9
55
suites: codeql-suites
66
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
77
groups:

ql/ql/src/codeql_ql/StructuredLogs.qll

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ module KindPredicatesLog {
271271

272272
float getResultSize() { result = this.getFloat("resultSize") }
273273

274+
Array getRA(string ordering) { result = this.getObject("ra").getArray(ordering) }
275+
276+
string getAnOrdering() { exists(this.getRA(result)) }
277+
274278
override string toString() {
275279
if exists(this.getPredicateName())
276280
then result = this.getPredicateName()
@@ -335,8 +339,12 @@ module KindPredicatesLog {
335339
raExpr.getLine() = i
336340
}
337341

342+
Array getCounts() { result = this.getArray("counts") }
343+
338344
float getCount(int i) { result = getRanked(this.getArray("counts"), i) }
339345

346+
Array getDuplicationPercentage() { result = this.getArray("duplicationPercentages") }
347+
340348
float getDuplicationPercentage(int i) {
341349
result = getRanked(this.getArray("duplicationPercentages"), i)
342350
}
@@ -374,6 +382,123 @@ module KindPredicatesLog {
374382
string getPosition() { result = this.getString("position") }
375383

376384
Predicate getPredicate() { result = getPredicateFromPosition(this.getPosition()) }
385+
386+
/**
387+
* Gets the RA for this event. Unlike recursive predicates, a COMPUTE_SIMPLE
388+
* event only has one pipeline ordering (and it's named "pipeline").
389+
*/
390+
PipeLine getPipeLine() { result = this.getObject("ra").getArray("pipeline") }
391+
}
392+
393+
/** Gets the `index`'th event that's evaluated by `recursive`. */
394+
private InLayer layerEventRank(ComputeRecursive recursive, int index) {
395+
result =
396+
rank[index + 1](InLayer cand, int startline, string filepath |
397+
cand.getComputeRecursiveEvent() = recursive and
398+
cand.hasLocationInfo(filepath, startline, _, _, _)
399+
|
400+
cand order by filepath, startline
401+
)
402+
}
403+
404+
/**
405+
* Gets the first predicate that's evaluated in an iteration
406+
* of the SCC computation rooted at `recursive`.
407+
*/
408+
private InLayer firstPredicate(ComputeRecursive recursive) {
409+
result = layerEventRank(recursive, 0)
410+
}
411+
412+
/**
413+
* Gets the last predicate that's evaluated in an iteration
414+
* of the SCC computation rooted at `recursive`.
415+
*/
416+
private InLayer lastPredicate(ComputeRecursive recursive) {
417+
exists(int n |
418+
result = layerEventRank(recursive, n) and
419+
not exists(layerEventRank(recursive, n + 1))
420+
)
421+
}
422+
423+
/**
424+
* Holds if the predicate represented by `next` was evaluated after the
425+
* predicate represented by `prev` in the SCC computation rooted at `recursive`.
426+
*/
427+
predicate successor(ComputeRecursive recursive, InLayer prev, InLayer next) {
428+
exists(int index |
429+
layerEventRank(recursive, index) = prev and
430+
layerEventRank(recursive, index + 1) = next
431+
)
432+
}
433+
434+
bindingset[this]
435+
signature class ResultSig;
436+
437+
/**
438+
* A signature for generically traversing a SCC computation.
439+
*/
440+
signature module Fold<ResultSig R> {
441+
/**
442+
* Gets the base case for the fold. That is, the initial value that
443+
* is produced from the first evaluation of the first IN_LAYER event
444+
* in the recursive evaluation.
445+
*/
446+
bindingset[run]
447+
R base(PipeLineRun run);
448+
449+
/**
450+
* Gets the recursive case for the fold. That is, `r` is the accumulation
451+
* of the previous evaluations, and `run` is the pipeline of the next IN_LAYER
452+
* event that is evaluated.
453+
*/
454+
bindingset[run, r]
455+
R fold(PipeLineRun run, R r);
456+
}
457+
458+
module Iterate<ResultSig R, Fold<R> F> {
459+
private R iterate(ComputeRecursive recursive, int iteration, InLayer pred) {
460+
// Case: The first iteration
461+
iteration = 0 and
462+
(
463+
// Subcase: The first predicate in the first iteration
464+
pred = firstPredicate(recursive) and
465+
result = F::base(pred.getPipelineRuns().getRun(0))
466+
or
467+
// Subcase: The predicate has a predecessor
468+
exists(InLayer pred0, R r |
469+
successor(recursive, pred0, pred) and
470+
r = iterate(recursive, 0, pred0) and
471+
result = F::fold(pred.getPipelineRuns().getRun(0), r)
472+
)
473+
)
474+
or
475+
// Case: Not the first iteration
476+
iteration > 0 and
477+
(
478+
// Subcase: The first predicate in the iteration
479+
pred = firstPredicate(recursive) and
480+
exists(InLayer last, R r |
481+
last = lastPredicate(recursive) and
482+
r = iterate(recursive, iteration - 1, last) and
483+
result = F::fold(pred.getPipelineRuns().getRun(iteration), r)
484+
)
485+
or
486+
// Subcase: The predicate has a predecessor in the same iteration
487+
exists(InLayer pred0, R r |
488+
successor(recursive, pred0, pred) and
489+
r = iterate(recursive, iteration, pred0) and
490+
result = F::fold(pred.getPipelineRuns().getRun(iteration), r)
491+
)
492+
)
493+
}
494+
495+
R iterate(ComputeRecursive recursive) {
496+
exists(int iteration, InLayer pred |
497+
pred = lastPredicate(recursive) and
498+
result = iterate(recursive, iteration, pred) and
499+
not exists(iterate(recursive, iteration + 1, pred))
500+
)
501+
}
377502
}
378503

379504
class ComputeRecursive extends SummaryEvent {
@@ -382,6 +507,20 @@ module KindPredicatesLog {
382507

383508
class InLayer extends SummaryEvent {
384509
InLayer() { evaluationStrategy = "IN_LAYER" }
510+
511+
string getMainHash() { result = this.getString("mainHash") }
512+
513+
ComputeRecursive getComputeRecursiveEvent() { result.getRAHash() = this.getMainHash() }
514+
515+
Array getPredicateIterationMillis() { result = this.getArray("predicateIterationMillis") }
516+
517+
float getPredicateIterationMillis(int i) {
518+
result = getRanked(this.getArray("predicateIterationMillis"), i)
519+
}
520+
521+
PipeLineRuns getPipelineRuns() { result = this.getArray("pipelineRuns") }
522+
523+
float getDeltaSize(int i) { result = getRanked(this.getArray("deltaSizes"), i) }
385524
}
386525

387526
class ComputedExtensional extends SummaryEvent {

ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,12 @@ module JSON {
18661866
/** Gets the location of this element. */
18671867
final L::Location getLocation() { json_ast_node_info(this, _, _, result) }
18681868

1869+
predicate hasLocationInfo(
1870+
string filepath, int startline, int startcolumn, int endline, int endcolumn
1871+
) {
1872+
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
1873+
}
1874+
18691875
/** Gets the parent of this element. */
18701876
final AstNode getParent() { json_ast_node_info(this, result, _, _) }
18711877

ql/ql/src/queries/performance/LargeJoinOrder.ql

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,37 @@ import KindPredicatesLog
1616
float getBadness(ComputeSimple simple) {
1717
exists(float maxTupleCount, float resultSize, float largestDependency, float denom |
1818
resultSize = simple.getResultSize() and
19-
maxTupleCount = max(simple.getPipelineRun().getCount(_)) and
19+
extractInformation(simple, maxTupleCount, _, _, _) and
2020
largestDependency = max(simple.getDependencies().getADependency().getResultSize()) and
2121
denom = resultSize.maximum(largestDependency) and
2222
denom > 0 and // avoid division by zero (which would create a NaN result).
2323
result = maxTupleCount / denom
2424
)
2525
}
2626

27-
from ComputeSimple evt, float f
28-
where f = getBadness(evt) and f > 1.5
29-
select evt, f order by f desc
27+
pragma[nomagic]
28+
predicate hasPipelineRun(ComputeSimple simple, PipeLineRun run) { run = simple.getPipelineRun() }
29+
30+
predicate extractInformation(
31+
ComputeSimple simple, float maxTupleCount, Array tuples, Array duplicationPercentages, Array ra
32+
) {
33+
exists(PipeLineRun run |
34+
hasPipelineRun(simple, run) and
35+
maxTupleCount = max(run.getCount(_)) and
36+
tuples = run.getCounts() and
37+
duplicationPercentages = run.getDuplicationPercentage() and
38+
ra = simple.getRA()
39+
)
40+
}
41+
42+
from
43+
ComputeSimple evt, float badness, float maxTupleCount, Array tuples, Array duplicationPercentages,
44+
Array ra, int index
45+
where
46+
badness = getBadness(evt) and
47+
badness > 1.5 and
48+
extractInformation(evt, maxTupleCount, tuples, duplicationPercentages, ra)
49+
select evt.getPredicateName() as predicate_name, badness, index,
50+
tuples.getFloat(index) as tuple_count,
51+
duplicationPercentages.getFloat(index) as duplication_percentage, ra.getString(index) order by
52+
badness desc
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Shows a list of the "slow" predicates by tuple sum.
3+
*/
4+
5+
import ql
6+
import codeql_ql.StructuredLogs
7+
import KindPredicatesLog
8+
9+
module SumCounts implements Fold<int> {
10+
int base(PipeLineRun run) { result = sum(int i | | run.getCount(i)) }
11+
12+
bindingset[s]
13+
int fold(PipeLineRun run, int s) { result = sum(int i | | run.getCount(i)) + s }
14+
}
15+
16+
int sumTuples(SummaryEvent event) {
17+
result = strictsum(int i | | event.(ComputeSimple).getPipelineRun().getCount(i))
18+
or
19+
result = Iterate<int, SumCounts>::iterate(event)
20+
}
21+
22+
int predicateRank(SummaryEvent evt) {
23+
evt = rank[result](SummaryEvent y, int s | s = sumTuples(y) | y order by s desc)
24+
}
25+
26+
from SummaryEvent evt, int s
27+
where predicateRank(evt) < 50 and s = sumTuples(evt)
28+
select evt, s order by s desc

0 commit comments

Comments
 (0)