From 4042bbec5bb604d325bc0e9e1a189fdada012b90 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 29 Apr 2026 11:11:44 +0200 Subject: [PATCH 1/7] Swift: Add type inference tests --- .../type-inference/type-inference.expected | 0 .../type-inference/type-inference.ql | 91 ++ .../type-inference/typeinference.swift | 1372 +++++++++++++++++ 3 files changed, 1463 insertions(+) create mode 100644 swift/ql/test/library-tests/type-inference/type-inference.expected create mode 100644 swift/ql/test/library-tests/type-inference/type-inference.ql create mode 100644 swift/ql/test/library-tests/type-inference/typeinference.swift diff --git a/swift/ql/test/library-tests/type-inference/type-inference.expected b/swift/ql/test/library-tests/type-inference/type-inference.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/ql/test/library-tests/type-inference/type-inference.ql b/swift/ql/test/library-tests/type-inference/type-inference.ql new file mode 100644 index 00000000000..cd51687e8af --- /dev/null +++ b/swift/ql/test/library-tests/type-inference/type-inference.ql @@ -0,0 +1,91 @@ +import swift +import TestUtils +import utils.test.InlineExpectationsTest + +pragma[nomagic] +private predicate declHasPotentialCommentAt(Decl d, string path, int line) { + d.getLocation().hasLocationInfo(path, line + 1, _, _, _) +} + +pragma[nomagic] +private SingleLineComment getPrecedingComment(Decl d) { + exists(string path, int line | + declHasPotentialCommentAt(d, path, line) and + result.getLocation().hasLocationInfo(path, line, _, _, _) + ) +} + +module ResolveTest implements TestSig { + string getARelevantTag() { result = "target" } + + private predicate declHasName(Decl c, string value) { + exists(string s | + s = getPrecedingComment(c).getText() and + value = s.substring(3, s.length() - 1) + ) + or + not exists(getPrecedingComment(c)) and + value = [c.(EnumElementDecl).getName(), c.(Function).getName()] + } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(AstNode source, Decl target | + location = source.getLocation() and + element = source.toString() and + target = + [ + source.(CallExpr).getStaticTarget().(Decl), source.(MethodLookupExpr).getMember(), + source.(EnumElementPattern).getElement() + ] and + declHasName(target, value) and + tag = "target" and + toBeTested(source) and + toBeTested(target) + ) + } +} + +private Type getTypeAt(Type t, string path) { + path = "" and + result = t.getUnderlyingType() + or + exists(BoundGenericType b, GenericTypeDecl decl | + b = t and + decl = b.getDeclaration() + | + exists(string prefix, string suffix, int i | + result = getTypeAt(b.getArgType(i).getUnderlyingType(), suffix) and + prefix = decl.getName() + "<" + decl.getGenericTypeParam(i).getName() + ">" and + if suffix = "" then path = prefix else path = prefix + "." + suffix + ) + ) +} + +module TypeTest implements TestSig { + string getARelevantTag() { result = ["type", "certainType"] } + + predicate tagIsOptional(string expectedTag) { expectedTag = "type" } + + predicate hasActualResult(Location location, string element, string tag, string value) { none() } + + predicate hasOptionalResult(Location location, string element, string tag, string value) { + exists(Locatable e, string path, Type t, Type t0 | + t = [e.(Expr).getType(), e.(VarDecl).getType()] and + tag = "type" and + location = e.getLocation() and + t0 = getTypeAt(t, path) and + exists(string name, string at | + name = t0.(AnyGenericType).getDeclaration().getName() + or + not t0 instanceof AnyGenericType and + name = t0.getName() + | + (if path = "" then at = "" else at = "@" + path) and + value = element + at + ":" + name and + element = e.toString() + ) + ) + } +} + +import MakeTest> diff --git a/swift/ql/test/library-tests/type-inference/typeinference.swift b/swift/ql/test/library-tests/type-inference/typeinference.swift new file mode 100644 index 00000000000..0e718fa9b92 --- /dev/null +++ b/swift/ql/test/library-tests/type-inference/typeinference.swift @@ -0,0 +1,1372 @@ +var topLevelDecl : Int = 0 +0 +topLevelDecl + 1 // $ type=topLevelDecl:Int + +class C { + var myInt : Int + // C.init + init(n: Int) { + myInt = n // $ type=n:Int + } + + // C.getMyInt + func getMyInt() -> Int { + return myInt // $ type=.myInt:Int + } +} + +class Derived : C { + // Derived.init + init() { + super.init(n: 0) // $ type=super:C target=C.init + } + + // Derived.callGetMyInt + func callGetMyInt() -> Int { + let x = getMyInt(); // $ type=x:Int target=C.getMyInt + return x + } +} + +class Generic { + var value : T + // Generic.init + init(v: T) { + value = v // $ type=v:T + } + + // Generic.getValue + func getValue() -> T { + return value // $ type=.value:T + } +} + +class GenericDerived : Generic { + // GenericDerived.init + init() { + super.init(v: 0) // $ type=super@Generic:Int target=Generic.init + } +} + +func testGeneric() { + let g = Generic(v: 42) // $ type=g@Generic:Int target=Generic.init + let x = g.getValue() // $ type=x:Int target=Generic.getValue + + let gd = GenericDerived() // $ type=gd:GenericDerived target=GenericDerived.init + let y = gd.getValue() // $ type=y:Int target=Generic.getValue +} + +// --- Protocols and protocol conformance --- + +protocol Shape { + // Shape.area + func area() -> Double +} + +struct Circle : Shape { + var radius : Double + + // Circle.init + init(radius: Double) { + self.radius = radius // $ type=radius:Double + } + + // Circle.area + func area() -> Double { + return 3.14159 * radius * radius // $ type=.radius:Double + } +} + +struct Rectangle : Shape { + var width : Double + var height : Double + + // Rectangle.init + init(width: Double, height: Double) { + self.width = width // $ type=width:Double + self.height = height // $ type=height:Double + } + + // Rectangle.area + func area() -> Double { + return width * height // $ type=.width:Double + } +} + +func testProtocol() { + let c = Circle(radius: 5.0) // $ type=c:Circle target=Circle.init + let a1 = c.area() // $ type=a1:Double target=Circle.area + + let r = Rectangle(width: 3.0, height: 4.0) // $ type=r:Rectangle target=Rectangle.init + let a2 = r.area() // $ type=a2:Double target=Rectangle.area +} + +// --- Extensions --- + +extension C { + // C.doubled + func doubled() -> Int { + return myInt * 2 // $ type=.myInt:Int + } +} + +func testExtension() { + let obj = C(n: 10) // $ target=C.init + let d = obj.doubled() // $ type=d:Int target=C.doubled +} + +// --- Static methods --- + +class MathUtils { + // MathUtils.square + static func square(x: Int) -> Int { + return x * x // $ type=x:Int + } + + // MathUtils.cube + class func cube(x: Int) -> Int { + return x * x * x // $ type=x:Int + } +} + +func testStaticMethods() { + let s = MathUtils.square(x: 4) // $ type=s:Int target=MathUtils.square + let cu = MathUtils.cube(x: 3) // $ type=cu:Int target=MathUtils.cube +} + +// --- Overloading --- + +class Overloaded { + // Overloaded.process(_:Int) + func process(_ x: Int) -> Int { + return x + 1 // $ type=x:Int + } + + // Overloaded.process(_:String) + func process(_ s: String) -> String { + return s // $ type=s:String + } +} + +func testOverloading() { + let o = Overloaded() // $ target=init() + let r1 = o.process(42) // $ type=r1:Int target=Overloaded.process(_:Int) + let r2 = o.process("hello") // $ type=r2:String target=Overloaded.process(_:String) +} + +// --- Generic functions --- + +// identity +func identity(_ x: T) -> T { + return x // $ type=x:T +} + +// makePair +func makePair(_ a: A, _ b: B) -> (A, B) { + return (a, b) // $ type=a:A +} + +func testGenericFunctions() { + let i = identity(42) // $ type=i:Int target=identity + let s = identity("hello") // $ type=s:String target=identity + let p = makePair(1, "two") // $ target=makePair +} + +// --- Generic constraints --- + +struct Pair { + var first : A + var second : B + + // Pair.init + init(first: A, second: B) { + self.first = first // $ type=first:A + self.second = second // $ type=second:B + } + + // Pair.getFirst + func getFirst() -> A { + return first // $ type=.first:A + } + + // Pair.getSecond + func getSecond() -> B { + return second // $ type=.second:B + } +} + +func testGenericStruct() { + let p = Pair(first: 1, second: "x") // $ target=Pair.init type=p@Pair:Int type=p@Pair:String + let f = p.getFirst() // $ type=f:Int target=Pair.getFirst + let sc = p.getSecond() // $ type=sc:String target=Pair.getSecond +} + +// --- Enums with associated values --- + +enum Result { + // Result.success + case success(T) + // Result.failure + case failure(String) + + // Result.getValue + func getValue() -> T? { + switch self { + case .success(let v): // $ target=Result.success + return v // $ type=v:T + case .failure: // $ target=Result.failure + return nil + } + } +} + +func testEnum() { + let r = Result.success(42) // $ type=r@Result:Int target=Result.success + let v = r.getValue() // $ target=Result.getValue + + let r2 : Result = .success(42) // $ type=r2@Result:Int target=Result.success + let v2 = r2.getValue() // $ target=Result.getValue +} + +// --- Closures and type inference --- + +// applyTransform +func applyTransform(_ value: T, _ transform: (T) -> U) -> U { + return transform(value) +} + +func testClosures() { + let result = applyTransform(5, { x in x * 2 }) // $ target=applyTransform type=result:Int + let strings = applyTransform(10, { x in String(x) }) // $ target=applyTransform type=strings:String +} + +// --- Subscripts --- + +struct Matrix { + var data : [[Int]] + + // Matrix.init + init(data: [[Int]]) { + self.data = data + } + + // Matrix.rowCount + func rowCount() -> Int { + return data.count + } +} + +func testSubscripts() { + let m = Matrix(data: [[1, 2], [3, 4]]) // $ target=Matrix.init + let rc = m.rowCount() // $ type=rc:Int target=Matrix.rowCount +} + +// --- Nested types --- + +class Outer { + class Inner { + var value : Int + + // Outer.Inner.init + init(value: Int) { + self.value = value // $ type=value:Int + } + + // Outer.Inner.getValue + func getValue() -> Int { + return self.value // $ type=.value:Int + } + } +} + +func testNestedTypes() { + let inner = Outer.Inner(value: 99) // $ type=inner:Inner target=Outer.Inner.init + let v = inner.getValue() // $ type=v:Int target=Outer.Inner.getValue +} + +// --- Method chaining --- + +class Builder { + var value : Int = 0 + + // Builder.init + init() {} + + // Builder.set + func set(_ v: Int) -> Builder { + value = v + return self + } + + // Builder.add + func add(_ v: Int) -> Builder { + value += v + return self + } + + // Builder.build + func build() -> Int { + return value // $ type=.value:Int + } +} + +func testChaining() { + let b = Builder() // $ type=b:Builder target=Builder.init + let result = b.set(10).add(5).build() // $ type=result:Int target=Builder.set target=Builder.add target=Builder.build +} + +// --- Protocol with associated type-like patterns (using generics) --- + +protocol Container { + associatedtype Item + // Container.getItem + func getItem() -> Item + // Container.count + func count() -> Int +} + +struct IntContainer : Container { + typealias Item = Int + var items : [Int] + + // IntContainer.init + init(items: [Int]) { + self.items = items + } + + // IntContainer.getItem + func getItem() -> Int { + return items[0] + } + + // IntContainer.count + func count() -> Int { + return items.count + } +} + +func testAssociatedTypes() { + let ic = IntContainer(items: [1, 2, 3]) // $ type=ic:IntContainer target=IntContainer.init + let item = ic.getItem() // $ type=item:Int target=IntContainer.getItem + let cnt = ic.count() // $ type=cnt:Int target=IntContainer.count +} + +// --- Default parameter values --- + +class Config { + // Config.init + init() {} + + // Config.setup + func setup(retries: Int = 3, timeout: Double = 30.0) -> Int { + return retries // $ type=retries:Int + } +} + +func testDefaultParams() { + let cfg = Config() // $ type=cfg:Config target=Config.init + let r1 = cfg.setup() // $ type=r1:Int target=Config.setup + let r2 = cfg.setup(retries: 5) // $ type=r2:Int target=Config.setup + let r3 = cfg.setup(retries: 2, timeout: 60.0) // $ type=r3:Int target=Config.setup +} + +// --- Multiple inheritance (protocol conformance) --- + +protocol Printable { + // Printable.display + func display() -> String +} + +protocol Identifiable { + // Identifiable.id + func id() -> Int +} + +class Entity : Printable, Identifiable { + var name : String + var entityId : Int + + // Entity.init + init(name: String, entityId: Int) { + self.name = name // $ type=name:String + self.entityId = entityId // $ type=entityId:Int + } + + // Entity.display + func display() -> String { + return name // $ type=.name:String + } + + // Entity.id + func id() -> Int { + return entityId // $ type=.entityId:Int + } +} + +func testMultipleProtocols() { + let e = Entity(name: "test", entityId: 42) // $ type=e:Entity target=Entity.init + let d = e.display() // $ type=d:String target=Entity.display + let eid = e.id() // $ type=eid:Int target=Entity.id +} + +// --- Computed properties accessed via methods --- + +class Temperature { + var celsius : Double + + // Temperature.init + init(celsius: Double) { + self.celsius = celsius // $ type=celsius:Double + } + + // Temperature.toCelsius + func toCelsius() -> Double { + return celsius // $ type=.celsius:Double + } + + // Temperature.toFahrenheit + func toFahrenheit() -> Double { + return celsius * 9.0 / 5.0 + 32.0 // $ type=.celsius:Double + } +} + +func testTemperature() { + let t = Temperature(celsius: 100.0) // $ type=t:Temperature target=Temperature.init + let c = t.toCelsius() // $ type=c:Double target=Temperature.toCelsius + let f = t.toFahrenheit() // $ type=f:Double target=Temperature.toFahrenheit +} + +// --- Inheritance with overriding --- + +class Animal { + // Animal.init + init() {} + + // Animal.speak + func speak() -> String { + return "..." + } +} + +class Dog : Animal { + // Dog.init + override init() { + super.init() // $ target=Animal.init + } + + // Dog.speak + override func speak() -> String { + return "Woof" + } + + // Dog.fetch + func fetch() -> String { + return "ball" + } +} + +class Cat : Animal { + // Cat.init + override init() { + super.init() // $ target=Animal.init + } + + // Cat.speak + override func speak() -> String { + return "Meow" + } +} + +func testOverriding() { + let d = Dog() // $ type=d:Dog target=Dog.init + let ds = d.speak() // $ type=ds:String target=Dog.speak + let df = d.fetch() // $ type=df:String target=Dog.fetch + + let ct = Cat() // $ type=ct:Cat target=Cat.init + let cs = ct.speak() // $ type=cs:String target=Cat.speak +} + +// --- Generic class with constraints --- + +protocol MyProtocol { + associatedtype MyType + + // MyProtocol.foo + func foo() -> Self + + // MyProtocol.bar + func bar() -> MyType +} + +class Wrapper { + var inner : T + + // Wrapper.init + init(_ inner: T) { + self.inner = inner // $ type=inner:T + } + + // Wrapper.get + func get() -> T { + return inner // $ type=.inner:T + } + + // Wrapper.callFoo + func callFoo() -> T { + let x = inner.foo(); // $ type=x:T target=MyProtocol.foo + return x + } + + // Wrapper.callBar + func callBar() -> T.MyType { + let x = inner.bar(); // $ type=x:MyType target=MyProtocol.bar + return x + } +} + +extension Int : MyProtocol { + typealias MyType = String + + // Int.foo + func foo() -> Int { + return self * 2 // $ type=self:Int + } + + // Int.bar + func bar() -> String { + return "number" + } +} + +func testConstrainedGeneric() { + let w = Wrapper(42) // $ type=w@Wrapper:Int target=Wrapper.init + let v = w.get() // $ type=v:Int target=Wrapper.get + let z = w.callFoo() // $ type=z:Int target=Wrapper.callFoo +} + +// --- Mutating methods on structs --- + +struct Counter { + var count : Int = 0 + + // Counter.increment + mutating func increment() { + count += 1 + } + + // Counter.getCount + func getCount() -> Int { + return count // $ type=.count:Int + } +} + +func testMutating() { + var ctr = Counter() // $ type=ctr:Counter target=init() + ctr.increment() // $ target=Counter.increment + let val = ctr.getCount() // $ type=val:Int target=Counter.getCount +} + +// ============================================================ +// Overload resolution tests +// ============================================================ + +// --- Overload by parameter type --- + +class OverloadByType { + // OverloadByType.handle(_:Int) + func handle(_ x: Int) -> String { + return "int" + } + + // OverloadByType.handle(_:Double) + func handle(_ x: Double) -> String { + return "double" + } + + // OverloadByType.handle(_:String) + func handle(_ x: String) -> String { + return "string" + } + + // OverloadByType.handle(_:Bool) + func handle(_ x: Bool) -> String { + return "bool" + } +} + +func testOverloadByType() { + let o = OverloadByType() // $ target=init() + let r1 = o.handle(42) // $ type=r1:String target=OverloadByType.handle(_:Int) + let r2 = o.handle(3.14) // $ type=r2:String target=OverloadByType.handle(_:Double) + let r3 = o.handle("hi") // $ type=r3:String target=OverloadByType.handle(_:String) + let r4 = o.handle(true) // $ type=r4:String target=OverloadByType.handle(_:Bool) +} + +// --- Overload by argument label --- + +class OverloadByLabel { + // OverloadByLabel.configure(width:) + func configure(width: Int) -> String { + return "width" + } + + // OverloadByLabel.configure(height:) + func configure(height: Int) -> String { + return "height" + } + + // OverloadByLabel.configure(width:height:) + func configure(width: Int, height: Int) -> String { + return "both" + } + + // OverloadByLabel.configure(size:) + func configure(size: Int) -> String { + return "size" + } +} + +func testOverloadByLabel() { + let o = OverloadByLabel() // $ target=init() + let r1 = o.configure(width: 10) // $ type=r1:String target=OverloadByLabel.configure(width:) + let r2 = o.configure(height: 20) // $ type=r2:String target=OverloadByLabel.configure(height:) + let r3 = o.configure(width: 10, height: 20) // $ type=r3:String target=OverloadByLabel.configure(width:height:) + let r4 = o.configure(size: 30) // $ type=r4:String target=OverloadByLabel.configure(size:) +} + +// --- Overload by arity (number of parameters) --- + +class OverloadByArity { + // OverloadByArity.compute() + func compute() -> Int { + return 0 + } + + // OverloadByArity.compute(_:Int) + func compute(_ x: Int) -> Int { + return x + } + + // OverloadByArity.compute(_:Int,_:Int) + func compute(_ x: Int, _ y: Int) -> Int { + return x + y + } + + // OverloadByArity.compute(_:Int,_:Int,_:Int) + func compute(_ x: Int, _ y: Int, _ z: Int) -> Int { + return x + y + z + } +} + +func testOverloadByArity() { + let o = OverloadByArity() // $ target=init() + let r0 = o.compute() // $ type=r0:Int target=OverloadByArity.compute() + let r1 = o.compute(1) // $ type=r1:Int target=OverloadByArity.compute(_:Int) + let r2 = o.compute(1, 2) // $ type=r2:Int target=OverloadByArity.compute(_:Int,_:Int) + let r3 = o.compute(1, 2, 3) // $ type=r3:Int target=OverloadByArity.compute(_:Int,_:Int,_:Int) +} + +// --- Overload by return type (contextual type) --- + +class OverloadByReturn { + // OverloadByReturn.create()->Int + func create() -> Int { + return 0 + } + + // OverloadByReturn.create()->String + func create() -> String { + return "" + } + + // OverloadByReturn.create()->Double + func create() -> Double { + return 0.0 + } +} + +func testOverloadByReturn() { + let o = OverloadByReturn() // $ target=init() + let r1 : Int = o.create() // $ type=r1:Int target=OverloadByReturn.create()->Int + let r2 : String = o.create() // $ type=r2:String target=OverloadByReturn.create()->String + let r3 : Double = o.create() // $ type=r3:Double target=OverloadByReturn.create()->Double +} + +// --- Overload: generic vs non-generic (non-generic preferred) --- + +class OverloadGenericVsConcrete { + // OverloadGenericVsConcrete.process(_:Int) + func process(_ x: Int) -> String { + return "concrete" + } + + // OverloadGenericVsConcrete.process(_:) + func process(_ x: T) -> String { + return "generic" + } +} + +func testOverloadGenericVsConcrete() { + let o = OverloadGenericVsConcrete() // $ target=init() + let r1 = o.process(42) // $ type=r1:String target=OverloadGenericVsConcrete.process(_:Int) + let r2 = o.process("hello") // $ type=r2:String target=OverloadGenericVsConcrete.process(_:) + let r3 = o.process(true) // $ type=r3:String target=OverloadGenericVsConcrete.process(_:) +} + +// --- Overload: free functions by parameter type --- + +// freeOverload(_:Int) +func freeOverload(_ x: Int) -> String { + return "int" +} + +// freeOverload(_:String) +func freeOverload(_ x: String) -> String { + return "string" +} + +// freeOverload(_:Double) +func freeOverload(_ x: Double) -> String { + return "double" +} + +func testFreeOverload() { + let r1 = freeOverload(42) // $ type=r1:String target=freeOverload(_:Int) + let r2 = freeOverload("hi") // $ type=r2:String target=freeOverload(_:String) + let r3 = freeOverload(1.5) // $ type=r3:String target=freeOverload(_:Double) +} + +// --- Overload: init overloading --- + +class MultiInit { + var value : String + + // MultiInit.init() + init() { + value = "default" + } + + // MultiInit.init(int:) + init(int: Int) { + value = "int" + } + + // MultiInit.init(str:) + init(str: String) { + value = str // $ type=str:String + } + + // MultiInit.init(x:y:) + init(x: Int, y: Int) { + value = "pair" + } + + // MultiInit.getValue + func getValue() -> String { + return value // $ type=.value:String + } +} + +func testInitOverloading() { + let m1 = MultiInit() // $ type=m1:MultiInit target=MultiInit.init() + let m2 = MultiInit(int: 5) // $ type=m2:MultiInit target=MultiInit.init(int:) + let m3 = MultiInit(str: "x") // $ type=m3:MultiInit target=MultiInit.init(str:) + let m4 = MultiInit(x: 1, y: 2) // $ type=m4:MultiInit target=MultiInit.init(x:y:) + let v = m1.getValue() // $ type=v:String target=MultiInit.getValue +} + +// --- Overload: static vs instance method --- + +class StaticVsInstance { + // StaticVsInstance.action()->instance + func action() -> String { + return "instance" + } + + // StaticVsInstance.action()->static + static func action() -> String { + return "static" + } + + // StaticVsInstance.init + init() {} +} + +func testStaticVsInstance() { + let o = StaticVsInstance() // $ target=StaticVsInstance.init + let r1 = o.action() // $ type=r1:String target=StaticVsInstance.action()->instance + let r2 = StaticVsInstance.action() // $ type=r2:String target=StaticVsInstance.action()->static +} + +// --- Overload: protocol extension default vs concrete implementation --- + +protocol Describable { + // Describable.describe + func describe() -> String +} + +extension Describable { + // Describable.describe(default) + func describe() -> String { + return "default" + } + + // Describable.extra + func extra() -> String { + return "extra" + } +} + +class DescribableImpl : Describable { + // DescribableImpl.init + init() {} + + // DescribableImpl.describe + func describe() -> String { + return "concrete" + } +} + +func testProtocolExtensionOverload() { + let d = DescribableImpl() // $ target=DescribableImpl.init + let r1 = d.describe() // $ type=r1:String target=DescribableImpl.describe + let r2 = d.extra() // $ type=r2:String target=Describable.extra +} + +// --- Overload: subclass override resolution --- + +class Base { + // Base.init + init() {} + + // Base.action + func action() -> String { + return "base" + } + + // Base.baseOnly + func baseOnly() -> String { + return "baseOnly" + } +} + +class Sub : Base { + // Sub.init + override init() { + super.init() // $ target=Base.init + } + + // Sub.action + override func action() -> String { + return "sub" + } + + // Sub.subOnly + func subOnly() -> String { + return "subOnly" + } +} + +class SubSub : Sub { + // SubSub.init + override init() { + super.init() // $ target=Sub.init + } + + // SubSub.action + override func action() -> String { + return "subsub" + } +} + +func testOverrideResolution() { + let b = Base() // $ target=Base.init + let rb = b.action() // $ type=rb:String target=Base.action + + let s = Sub() // $ target=Sub.init + let rs = s.action() // $ type=rs:String target=Sub.action + let rbo = s.baseOnly() // $ type=rbo:String target=Base.baseOnly + let rso = s.subOnly() // $ type=rso:String target=Sub.subOnly + + let ss = SubSub() // $ target=SubSub.init + let rss = ss.action() // $ type=rss:String target=SubSub.action + let rbo2 = ss.baseOnly() // $ type=rbo2:String target=Base.baseOnly + let rso2 = ss.subOnly() // $ type=rso2:String target=Sub.subOnly +} + +// --- Overload: by external vs internal parameter names --- + +class LabelVariants { + // LabelVariants.send(to:) + func send(to target: String) -> String { + return target // $ type=target:String + } + + // LabelVariants.send(from:) + func send(from source: String) -> String { + return source // $ type=source:String + } + + // LabelVariants.send(to:from:) + func send(to target: String, from source: String) -> String { + return target + source + } +} + +func testLabelVariants() { + let o = LabelVariants() // $ target=init() + let r1 = o.send(to: "x") // $ type=r1:String target=LabelVariants.send(to:) + let r2 = o.send(from: "y") // $ type=r2:String target=LabelVariants.send(from:) + let r3 = o.send(to: "x", from: "y") // $ type=r3:String target=LabelVariants.send(to:from:) +} + +// --- Overload: generic function with different constraint satisfaction --- + +protocol Numeric2 : Equatable { + // Numeric2.zero + static func zero() -> Self +} + +extension Int : Numeric2 { + // Int.zero + static func zero() -> Int { return 0 } +} + +extension Double : Numeric2 { + // Double.zero + static func zero() -> Double { return 0.0 } +} + +// constrainedId(_:Numeric2) +func constrainedId(_ x: T) -> T { + return x +} + +// constrainedId(_:Equatable) +func constrainedId(_ x: T) -> T { + return x +} + +func testConstrainedOverload() { + let r1 = constrainedId(42) // $ type=r1:Int target=constrainedId(_:Numeric2) + let r2 = constrainedId("hello") // $ type=r2:String target=constrainedId(_:Equatable) +} + +// --- Overload: methods on generic type specialized differently --- + +class Box { + var item : T + + // Box.init + init(_ item: T) { + self.item = item // $ type=item:T + } + + // Box.get + func get() -> T { + return item // $ type=.item:T + } + + // Box.replace + func replace(_ newItem: T) { + item = newItem // $ type=newItem:T + } +} + +func testGenericMethodResolution() { + let intBox = Box(10) // $ type=intBox@Box:Int target=Box.init + let strBox = Box("hi") // $ type=strBox@Box:String target=Box.init + let v1 = intBox.get() // $ type=v1:Int target=Box.get + let v2 = strBox.get() // $ type=v2:String target=Box.get + intBox.replace(20) // $ target=Box.replace + strBox.replace("bye") // $ target=Box.replace +} + +// --- Overload: convenience init vs designated init --- + +class Widget { + var name : String + var size : Int + + // Widget.init(name:size:) + init(name: String, size: Int) { + self.name = name // $ type=name:String + self.size = size // $ type=size:Int + } + + // Widget.init(name:) + convenience init(name: String) { + self.init(name: name, size: 1) // $ target=Widget.init(name:size:) + } + + // Widget.init(size:) + convenience init(size: Int) { + self.init(name: "default", size: size) // $ target=Widget.init(name:size:) + } +} + +func testConvenienceInit() { + let w1 = Widget(name: "a", size: 5) // $ type=w1:Widget target=Widget.init(name:size:) + let w2 = Widget(name: "b") // $ type=w2:Widget target=Widget.init(name:) + let w3 = Widget(size: 10) // $ type=w3:Widget target=Widget.init(size:) +} + +// --- Overload: methods with closure parameters of different signatures --- + +class Processor { + // Processor.init + init() {} + + // Processor.apply(_:(Int)->Int) + func apply(_ f: (Int) -> Int) -> Int { + return f(0) + } + + // Processor.apply(_:(String)->String) + func apply(_ f: (String) -> String) -> String { + return f("") + } + + // Processor.apply(_:(Int,Int)->Int) + func apply(_ f: (Int, Int) -> Int) -> Int { + return f(0, 0) + } +} + +func testClosureOverload() { + let p = Processor() // $ target=Processor.init + let r1 = p.apply({ x in x + 1 }) // $ type=r1:Int target=Processor.apply(_:(Int)->Int) + let r2 = p.apply({ s in s + "!" }) // $ type=r2:String target=Processor.apply(_:(String)->String) + let r3 = p.apply({ x, y in x + y }) // $ type=r3:Int target=Processor.apply(_:(Int,Int)->Int) +} + +// --- Overload: subscript overloading --- + +class MultiSubscript { + var data : [Int] = [1, 2, 3] + var dict : [String: Int] = ["a": 1] + + // MultiSubscript.init + init() {} + + // MultiSubscript.get(_:) + func get(_ index: Int) -> Int { + return data[index] + } + + // MultiSubscript.get(_:String) + func get(_ key: String) -> Int { + return dict[key] ?? 0 + } +} + +func testMethodSubscriptLike() { + let ms = MultiSubscript() // $ target=MultiSubscript.init + let r1 = ms.get(0) // $ type=r1:Int target=MultiSubscript.get(_:) + let r2 = ms.get("a") // $ type=r2:Int target=MultiSubscript.get(_:String) +} + +// ============================================================ +// Type parameters with constraints +// ============================================================ + +// --- where clause on generic function --- + +// minOf(_:_:) +func minOf(_ a: T, _ b: T) -> T { + if a < b { return a } else { return b } +} + +// maxOf(_:_:) +func maxOf(_ a: T, _ b: T) -> T where T : Comparable { + if a > b { return a } else { return b } +} + +func testWhereClause() { + let m1 = minOf(3, 7) // $ type=m1:Int target=minOf(_:_:) + let m2 = minOf("a", "z") // $ type=m2:String target=minOf(_:_:) + let m3 = maxOf(3, 7) // $ type=m3:Int target=maxOf(_:_:) + let m4 = maxOf("a", "z") // $ type=m4:String target=maxOf(_:_:) +} + +// --- Multiple constraints on a single type parameter --- + +protocol Displayable2 { + // Displayable2.display + func display() -> String +} + +protocol Sortable { + // Sortable.sortKey + func sortKey() -> Int +} + +struct TaggedItem : Displayable2, Sortable, Equatable { + var tag : String + var priority : Int + + // TaggedItem.init + init(tag: String, priority: Int) { + self.tag = tag // $ type=tag:String + self.priority = priority // $ type=priority:Int + } + + // TaggedItem.display + func display() -> String { + return tag // $ type=.tag:String + } + + // TaggedItem.sortKey + func sortKey() -> Int { + return priority // $ type=.priority:Int + } +} + +// showAndSort(_:) +func showAndSort(_ item: T) -> String { + return item.display() // $ target=Displayable2.display +} + +// showSortAndCompare(_:_:) +func showSortAndCompare(_ a: T, _ b: T) -> Bool where T : Displayable2, T : Sortable, T : Equatable { + return a == b +} + +func testMultipleConstraints() { + let item = TaggedItem(tag: "x", priority: 1) // $ target=TaggedItem.init + let s = showAndSort(item) // $ type=s:String target=showAndSort(_:) + let eq = showSortAndCompare(item, item) // $ type=eq:Bool target=showSortAndCompare(_:_:) +} + +// --- Generic class with multiple constrained type parameters --- + +class SortedPair { + var first : T + var second : U + + // SortedPair.init + init(first: T, second: U) { + self.first = first // $ type=first:T + self.second = second // $ type=second:U + } + + // SortedPair.isFirstSmaller + func isFirstSmaller(than other: T) -> Bool { + return first < other // $ type=other:T + } + + // SortedPair.isSecondSmaller + func isSecondSmaller(than other: U) -> Bool { + return second < other // $ type=other:U + } +} + +func testMultiConstrainedParams() { + let sp = SortedPair(first: 3, second: "b") // $ target=SortedPair.init + let r1 = sp.isFirstSmaller(than: 5) // $ type=r1:Bool target=SortedPair.isFirstSmaller + let r2 = sp.isSecondSmaller(than: "z") // $ type=r2:Bool target=SortedPair.isSecondSmaller +} + +// --- Associated type constraints (same-type constraint) --- + +protocol ElementContainer { + associatedtype Element + // ElementContainer.first + func first() -> Element +} + +struct IntArray : ElementContainer { + typealias Element = Int + var items : [Int] + + // IntArray.init + init(items: [Int]) { + self.items = items + } + + // IntArray.first + func first() -> Int { + return items[0] + } +} + +struct StringArray : ElementContainer { + typealias Element = String + var items : [String] + + // StringArray.init + init(items: [String]) { + self.items = items + } + + // StringArray.first + func first() -> String { + return items[0] + } +} + +// extractFirst(from:Int) +func extractFirst(from container: C) -> C.Element where C.Element == Int { + return container.first() // $ target=ElementContainer.first +} + +// extractFirst(from:String) +func extractFirst(from container: C) -> C.Element where C.Element == String { + return container.first() // $ target=ElementContainer.first +} + +func testSameTypeConstraint() { + let ia = IntArray(items: [10, 20]) // $ target=IntArray.init + let sa = StringArray(items: ["hi", "there"]) // $ target=StringArray.init + let r1 = extractFirst(from: ia) // $ type=r1:Int target=extractFirst(from:Int) + let r2 = extractFirst(from: sa) // $ type=r2:String target=extractFirst(from:String) +} + +// --- Superclass constraint on type parameter --- + +class Vehicle { + var speed : Int + + // Vehicle.init + init(speed: Int) { + self.speed = speed // $ type=speed:Int + } + + // Vehicle.describe + func describe() -> String { + return "vehicle" + } +} + +class Car : Vehicle { + // Car.init + override init(speed: Int) { + super.init(speed: speed) // $ target=Vehicle.init + } + + // Car.describe + override func describe() -> String { + return "car" + } + + // Car.honk + func honk() -> String { + return "beep" + } +} + +class Truck : Vehicle { + // Truck.init + override init(speed: Int) { + super.init(speed: speed) // $ target=Vehicle.init + } + + // Truck.describe + override func describe() -> String { + return "truck" + } + + // Truck.haul + func haul() -> String { + return "hauling" + } +} + +// describeVehicle(_:) +func describeVehicle(_ v: T) -> String { + return v.describe() // $ target=Vehicle.describe +} + +func testSuperclassConstraint() { + let car = Car(speed: 100) // $ type=car:Car target=Car.init + let truck = Truck(speed: 60) // $ type=truck:Truck target=Truck.init + let d1 = describeVehicle(car) // $ type=d1:String target=describeVehicle(_:) + let d2 = describeVehicle(truck) // $ type=d2:String target=describeVehicle(_:) + let h = car.honk() // $ type=h:String target=Car.honk + let hl = truck.haul() // $ type=hl:String target=Truck.haul +} + +// --- Constrained extension methods --- + +protocol Summable { + // Summable.+ + static func +(lhs: Self, rhs: Self) -> Self +} + +extension Int : Summable {} +extension Double : Summable {} +extension String : Summable {} + +struct Accumulator { + var values : [T] + + // Accumulator.init + init(values: [T]) { + self.values = values + } + + // Accumulator.count + func count() -> Int { + return values.count + } +} + +extension Accumulator where T : Summable { + // Accumulator.total + func total() -> T { + return values[0] + values[1] // $ target=Summable.+ + } +} + +extension Accumulator where T : Equatable { + // Accumulator.contains + func contains(_ item: T) -> Bool { + return values.contains(where: { $0 == item }) + } +} + +func testConstrainedExtensions() { + let intAcc = Accumulator(values: [1, 2, 3]) // $ target=Accumulator.init + let cnt = intAcc.count() // $ type=cnt:Int target=Accumulator.count + let tot = intAcc.total() // $ type=tot:Int target=Accumulator.total + let has = intAcc.contains(2) // $ type=has:Bool target=Accumulator.contains +} + +// --- Generic method with its own constrained type parameter --- + +class Transformer { + // Transformer.init + init() {} + + // Transformer.transform + func transform(_ items: [T]) -> T { + return items[0] + items[1] // $ target=Summable.+ + } + + // Transformer.merge + func merge(_ a: A, _ b: B) -> Bool { + return true + } +} + +func testMethodTypeParams() { + let t = Transformer() // $ target=Transformer.init + let r1 = t.transform([3, 1, 2]) // $ type=r1:Int target=Transformer.transform + let r2 = t.transform(["c", "a", "b"]) // $ type=r2:String target=Transformer.transform + let r3 = t.merge(1, "x") // $ type=r3:Bool target=Transformer.merge +} + +// --- Recursive constraint (Comparable requiring Equatable) --- + +// clamp(_:min:max:) +func clamp(_ value: T, min lower: T, max upper: T) -> T { + if value < lower { return lower } + if value > upper { return upper } + return value +} + +func testRecursiveConstraint() { + let r1 = clamp(5, min: 0, max: 10) // $ type=r1:Int target=clamp(_:min:max:) + let r2 = clamp(3.5, min: 1.0, max: 2.0) // $ type=r2:Double target=clamp(_:min:max:) + let r3 = clamp("m", min: "a", max: "z") // $ type=r3:String target=clamp(_:min:max:) +} \ No newline at end of file From 5546025f12f30459eadf7cd7c6c192644b17f43e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 4 May 2026 08:19:28 +0000 Subject: [PATCH 2/7] update codeql documentation --- .../codeql-changelog/codeql-cli-2.25.3.rst | 124 ++++++++++++++++++ .../codeql-changelog/index.rst | 1 + 2 files changed, 125 insertions(+) create mode 100644 docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst new file mode 100644 index 00000000000..7fdf39c9c11 --- /dev/null +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst @@ -0,0 +1,124 @@ +.. _codeql-cli-2.25.3: + +========================== +CodeQL 2.25.3 (2026-05-01) +========================== + +.. contents:: Contents + :depth: 2 + :local: + :backlinks: none + +This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog `__, `relevant GitHub Changelog updates `__, `changes in the CodeQL extension for Visual Studio Code `__, and the `CodeQL Action changelog `__. + +Security Coverage +----------------- + +CodeQL 2.25.3 runs a total of 496 security queries when configured with the Default suite (covering 169 CWE). The Extended suite enables an additional 131 queries (covering 32 more CWE). + +CodeQL CLI +---------- + +Improvements +~~~~~~~~~~~~ + +* The :code:`codeql database finalize` command now accepts the :code:`--working-dir` flag. When specified, any extractor pre-finalize scripts will be run in that directory. If the flag is not used, the scripts will run in the source root directory (maintaining existing behavior). The flag will also be automatically passed through when running the higher-level + :code:`codeql database create` command. + +Query Packs +----------- + +Major Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +GitHub Actions +"""""""""""""" + +* Fixed alert messages in :code:`actions/artifact-poisoning/critical` and :code:`actions/artifact-poisoning/medium` as they previously included a redundant placeholder in the alert message that would on occasion contain a long block of yml that makes the alert difficult to understand. Also improved the wording to make it clearer that it is not the artifact that is being poisoned, but instead a potentially untrusted artifact that is consumed. Finally, changed the alert location to be the source, to align more with other queries reporting an artifact (e.g. zipslip) which is more useful. + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* Added :code:`AllocationFunction` models for :code:`aligned_alloc`, :code:`std::aligned_alloc`, and :code:`bsl::aligned_alloc`. +* The "Comparison of narrow type with wide type in loop condition" (:code:`cpp/comparison-with-wider-type`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. +* The "Multiplication result converted to larger type" (:code:`cpp/integer-multiplication-cast-to-long`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. +* The "Suspicious add with sizeof" (:code:`cpp/suspicious-add-sizeof`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. +* The "Wrong type of arguments to formatting function" (:code:`cpp/wrong-type-format-argument`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. +* The "Implicit function declaration" (:code:`cpp/implicit-function-declaration`) query has been upgraded to :code:`high` precision. However, for :code:`build mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. + +C# +"" + +* The query :code:`cs/useless-tostring-call` has been updated to avoid false positive results in calls to :code:`StringBuilder.AppendLine` and calls of the form :code:`base.ToString()`. Moreover, the alert message has been made more precise. + +JavaScript/TypeScript +""""""""""""""""""""" + +* The query :code:`js/missing-rate-limiting` now takes Fastify per-route rate limiting into account. + +Python +"""""" + +* The :code:`py/bind-socket-all-network-interfaces` query now uses the global data-flow library, leading to better precision and more results. Also, wrappers of :code:`socket.socket` in the :code:`eventlet` and :code:`gevent` libraries are now also recognized as socket binding operations. + +GitHub Actions +"""""""""""""" + +* The query :code:`actions/missing-workflow-permissions` no longer produces false positive results on reusable workflows where all callers set permissions. + +Language Libraries +------------------ + +Breaking Changes +~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* The deprecated :code:`NonThrowingFunction` class has been removed, use :code:`NonCppThrowingFunction` instead. +* The deprecated :code:`ThrowingFunction` class has been removed, use :code:`AlwaysSehThrowingFunction` instead. + +Major Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Swift +""""" + +* Upgraded to allow analysis of Swift 6.3. + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Java/Kotlin +""""""""""" + +* The queries "Resolving XML external entity in user-controlled data" (:code:`java/xxe`) and "Resolving XML external entity in user-controlled data from local source" (:code:`java/xxe-local`) now recognize sinks in the Woodstox StAX library when :code:`com.ctc.wstx.stax.WstxInputFactory` or :code:`org.codehaus.stax2.XMLInputFactory2` are used directly. + +Python +"""""" + +* The Python extractor now supports the new :code:`lazy import ...` and :code:`lazy from ... import ...` (as defined in `PEP-810 `__) that will be part of Python 3.15. + +GitHub Actions +"""""""""""""" + +* Removed false positive injection sink models for the :code:`context` input of :code:`docker/build-push-action` and the :code:`allowed-endpoints` input of :code:`step-security/harden-runner`. + +Deprecated APIs +~~~~~~~~~~~~~~~ + +C# +"" + +* The predicates :code:`get[L|R]Value` in the class :code:`Assignment` have been deprecated. Use :code:`get[Left|Right]Operand` instead. + +New Features +~~~~~~~~~~~~ + +C/C++ +""""" + +* Added a subclass :code:`AutoconfConfigureTestFile` of :code:`ConfigurationTestFile` that represents files created by GNU autoconf configure scripts to test the build configuration. diff --git a/docs/codeql/codeql-overview/codeql-changelog/index.rst b/docs/codeql/codeql-overview/codeql-changelog/index.rst index 32a8b4574bb..5835176a93f 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/index.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/index.rst @@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here Date: Mon, 4 May 2026 10:26:50 +0200 Subject: [PATCH 3/7] Docs: replace `build mode: none` with `build-mode: none` --- cpp/ql/src/CHANGELOG.md | 2 +- .../ImplicitFunctionDeclaration.qhelp | 2 +- .../Underspecified Functions/ImplicitFunctionDeclaration.ql | 2 +- cpp/ql/src/change-notes/released/1.6.1.md | 2 +- csharp/ql/lib/CHANGELOG.md | 4 ++-- csharp/ql/lib/change-notes/released/5.4.5.md | 4 ++-- .../codeql-overview/codeql-changelog/codeql-cli-2.24.0.rst | 4 ++-- .../codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index 80b9ad0e475..e677f584416 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -7,7 +7,7 @@ * The "Multiplication result converted to larger type" (`cpp/integer-multiplication-cast-to-long`) query has been upgraded to `high` precision. This query will now run in the default code scanning suite. * The "Suspicious add with sizeof" (`cpp/suspicious-add-sizeof`) query has been upgraded to `high` precision. This query will now run in the default code scanning suite. * The "Wrong type of arguments to formatting function" (`cpp/wrong-type-format-argument`) query has been upgraded to `high` precision. This query will now run in the default code scanning suite. -* The "Implicit function declaration" (`cpp/implicit-function-declaration`) query has been upgraded to `high` precision. However, for `build mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. +* The "Implicit function declaration" (`cpp/implicit-function-declaration`) query has been upgraded to `high` precision. However, for `build-mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. ## 1.6.0 diff --git a/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.qhelp b/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.qhelp index 90a98e1bf57..d6c612abc75 100644 --- a/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.qhelp +++ b/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.qhelp @@ -14,7 +14,7 @@ function may behave unpredictably.

This may indicate a misspelled function name, or that the required header containing the function declaration has not been included.

-

Note: This query is not compatible with build mode: none databases, and produces +

Note: This query is not compatible with build-mode: none databases, and produces no results on those databases.

diff --git a/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql b/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql index 00b29efbd0f..8e921faf211 100644 --- a/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql +++ b/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql @@ -18,7 +18,7 @@ import TooManyArguments import semmle.code.cpp.commons.Exclusions /* - * This query is not compatible with build mode: none databases, and produces + * This query is not compatible with build-mode: none databases, and produces * no results on those databases. */ diff --git a/cpp/ql/src/change-notes/released/1.6.1.md b/cpp/ql/src/change-notes/released/1.6.1.md index 83781b87c58..02ca1c2cd06 100644 --- a/cpp/ql/src/change-notes/released/1.6.1.md +++ b/cpp/ql/src/change-notes/released/1.6.1.md @@ -7,4 +7,4 @@ * The "Multiplication result converted to larger type" (`cpp/integer-multiplication-cast-to-long`) query has been upgraded to `high` precision. This query will now run in the default code scanning suite. * The "Suspicious add with sizeof" (`cpp/suspicious-add-sizeof`) query has been upgraded to `high` precision. This query will now run in the default code scanning suite. * The "Wrong type of arguments to formatting function" (`cpp/wrong-type-format-argument`) query has been upgraded to `high` precision. This query will now run in the default code scanning suite. -* The "Implicit function declaration" (`cpp/implicit-function-declaration`) query has been upgraded to `high` precision. However, for `build mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. +* The "Implicit function declaration" (`cpp/implicit-function-declaration`) query has been upgraded to `high` precision. However, for `build-mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index 32cd8f33c65..2e3f6c137ee 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -64,9 +64,9 @@ No user-facing changes. * When a code-scanning configuration specifies the `paths:` and/or `paths-ignore:` settings, these are now taken into account by the C# extractor's search for `.config`, `.props`, XML and project files. * Updated the generated .NET “models as data” runtime models to cover .NET 10. * C# 14: Support for *implicit* span conversions in the QL library. -* Basic extractor support for .NET 10 is now available. Extraction is supported for .NET 10 projects in both traced mode and `build mode: none`. However, code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. +* Basic extractor support for .NET 10 is now available. Extraction is supported for .NET 10 projects in both traced mode and `build-mode: none`. However, code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. * Added autobuilder and `build-mode: none` support for `.slnx` solution files. -* In `build mode: none`, .NET 10 is now used by default unless a specific .NET version is specified elsewhere. +* In `build-mode: none`, .NET 10 is now used by default unless a specific .NET version is specified elsewhere. * Added implicit reads of `System.Collections.Generic.KeyValuePair.Value` at taint-tracking sinks and at inputs to additional taint steps. As a result, taint-tracking queries will now produce more results when a container is tainted. ### Bug Fixes diff --git a/csharp/ql/lib/change-notes/released/5.4.5.md b/csharp/ql/lib/change-notes/released/5.4.5.md index a084df5f200..fc1e8b8c4ee 100644 --- a/csharp/ql/lib/change-notes/released/5.4.5.md +++ b/csharp/ql/lib/change-notes/released/5.4.5.md @@ -5,9 +5,9 @@ * When a code-scanning configuration specifies the `paths:` and/or `paths-ignore:` settings, these are now taken into account by the C# extractor's search for `.config`, `.props`, XML and project files. * Updated the generated .NET “models as data” runtime models to cover .NET 10. * C# 14: Support for *implicit* span conversions in the QL library. -* Basic extractor support for .NET 10 is now available. Extraction is supported for .NET 10 projects in both traced mode and `build mode: none`. However, code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. +* Basic extractor support for .NET 10 is now available. Extraction is supported for .NET 10 projects in both traced mode and `build-mode: none`. However, code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. * Added autobuilder and `build-mode: none` support for `.slnx` solution files. -* In `build mode: none`, .NET 10 is now used by default unless a specific .NET version is specified elsewhere. +* In `build-mode: none`, .NET 10 is now used by default unless a specific .NET version is specified elsewhere. * Added implicit reads of `System.Collections.Generic.KeyValuePair.Value` at taint-tracking sinks and at inputs to additional taint steps. As a result, taint-tracking queries will now produce more results when a container is tainted. ### Bug Fixes diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.0.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.0.rst index 9c228de1fc2..39b5ce0772d 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.0.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.0.rst @@ -152,9 +152,9 @@ C# * When a code-scanning configuration specifies the :code:`paths:` and/or :code:`paths-ignore:` settings, these are now taken into account by the C# extractor's search for :code:`.config`, :code:`.props`, XML and project files. * Updated the generated .NET “models as data” runtime models to cover .NET 10. * C# 14: Support for *implicit* span conversions in the QL library. -* Basic extractor support for .NET 10 is now available. Extraction is supported for .NET 10 projects in both traced mode and :code:`build mode: none`. However, code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. +* Basic extractor support for .NET 10 is now available. Extraction is supported for .NET 10 projects in both traced mode and :code:`build-mode: none`. However, code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. * Added autobuilder and :code:`build-mode: none` support for :code:`.slnx` solution files. -* In :code:`build mode: none`, .NET 10 is now used by default unless a specific .NET version is specified elsewhere. +* In :code:`build-mode: none`, .NET 10 is now used by default unless a specific .NET version is specified elsewhere. * Added implicit reads of :code:`System.Collections.Generic.KeyValuePair.Value` at taint-tracking sinks and at inputs to additional taint steps. As a result, taint-tracking queries will now produce more results when a container is tainted. Golang diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst index 7fdf39c9c11..88130515732 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.3.rst @@ -47,7 +47,7 @@ C/C++ * The "Multiplication result converted to larger type" (:code:`cpp/integer-multiplication-cast-to-long`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. * The "Suspicious add with sizeof" (:code:`cpp/suspicious-add-sizeof`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. * The "Wrong type of arguments to formatting function" (:code:`cpp/wrong-type-format-argument`) query has been upgraded to :code:`high` precision. This query will now run in the default code scanning suite. -* The "Implicit function declaration" (:code:`cpp/implicit-function-declaration`) query has been upgraded to :code:`high` precision. However, for :code:`build mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. +* The "Implicit function declaration" (:code:`cpp/implicit-function-declaration`) query has been upgraded to :code:`high` precision. However, for :code:`build-mode: none` databases, it no longer produces any results. The results in this mode were found to be very noisy and fundamentally imprecise. C# "" From 17fded4aa5636cad84fd1eb54be28bcb44207dbb Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 1 May 2026 15:15:32 +0200 Subject: [PATCH 4/7] Java: Delete old deprecated code. --- java/ql/lib/semmle/code/java/Expr.qll | 5 - java/ql/lib/semmle/code/java/Member.qll | 8 -- java/ql/lib/semmle/code/java/Statement.qll | 5 - java/ql/lib/semmle/code/java/Type.qll | 3 - .../code/java/controlflow/Dominance.qll | 51 -------- .../semmle/code/java/dataflow/FlowSources.qll | 8 -- .../semmle/code/java/dataflow/FlowSummary.qll | 10 -- .../semmle/code/java/dataflow/NullGuards.qll | 24 ---- .../java/dataflow/internal/DataFlowNodes.qll | 13 -- .../lib/semmle/code/java/frameworks/Jndi.qll | 12 -- .../frameworks/spring/SpringController.qll | 3 - .../AndroidCertificatePinningQuery.qll | 7 -- .../security/ArithmeticTaintedLocalQuery.qll | 48 +------ .../java/security/ArithmeticTaintedQuery.qll | 20 --- .../code/java/security/CommandLineQuery.qll | 33 ----- .../java/security/ExecTaintedLocalQuery.qll | 26 +--- ...rnallyControlledFormatStringLocalQuery.qll | 25 +--- ...alidationOfArrayConstructionLocalQuery.qll | 23 +--- ...properValidationOfArrayIndexLocalQuery.qll | 27 +--- .../java/security/NumericCastTaintedQuery.qll | 31 ----- .../security/ResponseSplittingLocalQuery.qll | 38 +----- .../java/security/SqlTaintedLocalQuery.qll | 29 +---- .../code/java/security/TaintedPathQuery.qll | 25 ---- .../java/security/UrlRedirectLocalQuery.qll | 20 +-- .../code/java/security/XssLocalQuery.qll | 29 +---- .../code/java/security/XxeLocalQuery.qll | 27 +--- .../src/semmle/code/xml/MyBatisMapperXML.qll | 117 ------------------ 27 files changed, 20 insertions(+), 647 deletions(-) delete mode 100644 java/ql/src/semmle/code/xml/MyBatisMapperXML.qll diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index 31135429e2d..c03be611067 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -2732,11 +2732,6 @@ class PatternExpr extends Expr { */ LocalVariableDeclExpr asBindingOrUnnamedPattern() { result = this } - /** - * DEPRECATED: alias for `asBindingOrUnnamedPattern`. - */ - deprecated LocalVariableDeclExpr asBindingPattern() { result = this.asBindingOrUnnamedPattern() } - /** * Gets this pattern cast to a record pattern. */ diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 23e08c4e6b6..0a8d80f4c36 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -810,14 +810,6 @@ class Field extends Member, ExprParent, @field, Variable { ) } - /** - * DEPRECATED: The result is always `this`. - */ - deprecated Field getSourceDeclaration() { result = this } - - /** DEPRECATED: This always holds. */ - deprecated predicate isSourceDeclaration() { any() } - override predicate isPublic() { Member.super.isPublic() or diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index e2c7779b43c..558e148d71e 100644 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -558,11 +558,6 @@ class ConstCase extends SwitchCase { class PatternCase extends SwitchCase { PatternCase() { exists(PatternExpr pe | pe.isNthChildOf(this, _)) } - /** - * DEPRECATED: alias for getPattern(0) - */ - deprecated PatternExpr getPattern() { result = this.getPattern(0) } - /** * Gets this case's `n`th pattern. */ diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index ef5cc5d941c..8a46d863de2 100644 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -637,9 +637,6 @@ class RefType extends Type, Annotatable, Modifiable, @reftype { this.(NestedType).getEnclosingType().getNestedName() + "$" + this.getName() = result } - /** DEPRECATED: Alias for `getNestedName`. */ - deprecated string nestedName() { result = this.getNestedName() } - /** * Gets the source declaration of this type. * diff --git a/java/ql/lib/semmle/code/java/controlflow/Dominance.qll b/java/ql/lib/semmle/code/java/controlflow/Dominance.qll index e2a50ba06df..de283e7c0a2 100644 --- a/java/ql/lib/semmle/code/java/controlflow/Dominance.qll +++ b/java/ql/lib/semmle/code/java/controlflow/Dominance.qll @@ -10,57 +10,6 @@ import java * Predicates for basic-block-level dominance. */ -/** - * DEPRECATED: Use `BasicBlock::immediatelyDominates` instead. - * - * The immediate dominance relation for basic blocks. - */ -deprecated predicate bbIDominates(BasicBlock dom, BasicBlock node) { - dom.immediatelyDominates(node) -} - -/** Exit points for basic-block control-flow. */ -private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode } - -/** Reversed `bbSucc`. */ -private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getASuccessor() } - -/** The immediate post-dominance relation on basic blocks. */ -deprecated predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) = - idominance(bbSink/1, bbPred/2)(_, dominator, node) - -/** - * DEPRECATED: Use `BasicBlock::strictlyDominates` instead. - * - * Holds if `dom` strictly dominates `node`. - */ -deprecated predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) { - dom.strictlyDominates(node) -} - -/** - * DEPRECATED: Use `BasicBlock::dominates` instead. - * - * Holds if `dom` dominates `node`. (This is reflexive.) - */ -deprecated predicate bbDominates(BasicBlock dom, BasicBlock node) { dom.dominates(node) } - -/** - * DEPRECATED: Use `BasicBlock::strictlyPostDominates` instead. - * - * Holds if `dom` strictly post-dominates `node`. - */ -deprecated predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) { - dom.strictlyPostDominates(node) -} - -/** - * DEPRECATED: Use `BasicBlock::postDominates` instead. - * - * Holds if `dom` post-dominates `node`. (This is reflexive.) - */ -deprecated predicate bbPostDominates(BasicBlock dom, BasicBlock node) { dom.postDominates(node) } - /** * The dominance frontier relation for basic blocks. * diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll index 8c6ac60eb24..f8bd1e60597 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll @@ -43,14 +43,6 @@ abstract class SourceNode extends DataFlow::Node { abstract string getThreatModel(); } -/** - * DEPRECATED: Use `ActiveThreatModelSource` instead. - * - * A class of data flow sources that respects the - * current threat model configuration. - */ -deprecated class ThreatModelFlowSource = ActiveThreatModelSource; - /** * A data flow source that is enabled in the current threat model configuration. */ diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll index 5995e57a4ed..b88db0272ce 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll @@ -8,14 +8,6 @@ import java private import internal.FlowSummaryImpl as Impl private import internal.DataFlowUtil -deprecated class SummaryComponent = Impl::Private::SummaryComponent; - -deprecated module SummaryComponent = Impl::Private::SummaryComponent; - -deprecated class SummaryComponentStack = Impl::Private::SummaryComponentStack; - -deprecated module SummaryComponentStack = Impl::Private::SummaryComponentStack; - /** A synthetic callable with a set of concrete call sites and a flow summary. */ abstract class SyntheticCallable extends string { bindingset[this] @@ -147,5 +139,3 @@ private class SummarizedSyntheticCallableAdapter extends SummarizedCallable::Ran ) } } - -deprecated class RequiredSummaryComponentStack = Impl::Private::RequiredSummaryComponentStack; diff --git a/java/ql/lib/semmle/code/java/dataflow/NullGuards.qll b/java/ql/lib/semmle/code/java/dataflow/NullGuards.qll index e10e5460907..77549c89d81 100644 --- a/java/ql/lib/semmle/code/java/dataflow/NullGuards.qll +++ b/java/ql/lib/semmle/code/java/dataflow/NullGuards.qll @@ -196,18 +196,6 @@ Expr basicNullGuard(Expr e, boolean branch, boolean isnull) { Guards_v3::nullGuard(result, any(GuardValue v | v.asBooleanValue() = branch), e, isnull) } -/** - * DEPRECATED: Use `basicNullGuard` instead. - * - * Gets an expression that directly tests whether a given expression, `e`, is null or not. - * - * If `result` evaluates to `branch`, then `e` is guaranteed to be null if `isnull` - * is true, and non-null if `isnull` is false. - */ -deprecated Expr basicOrCustomNullGuard(Expr e, boolean branch, boolean isnull) { - result = basicNullGuard(e, branch, isnull) -} - /** * Gets an expression that directly tests whether a given SSA variable is null or not. * @@ -218,18 +206,6 @@ Expr directNullGuard(SsaDefinition v, boolean branch, boolean isnull) { result = basicNullGuard(sameValue(v, _), branch, isnull) } -/** - * DEPRECATED: Use `nullGuardControls`/`nullGuardControlsBranchEdge` instead. - * - * Gets a `Guard` that tests (possibly indirectly) whether a given SSA variable is null or not. - * - * If `result` evaluates to `branch`, then `v` is guaranteed to be null if `isnull` - * is true, and non-null if `isnull` is false. - */ -deprecated Guard nullGuard(SsaDefinition v, boolean branch, boolean isnull) { - result = directNullGuard(v, branch, isnull) -} - /** * Holds if there exists a null check on `v`, such that taking the branch edge * from `bb1` to `bb2` implies that `v` is guaranteed to be null if `isnull` is diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll index a280e531f91..8957442b39a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll @@ -198,19 +198,6 @@ module Public { or result = this.getType() and not exists(this.getImprovedTypeBound()) } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - deprecated predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/Jndi.qll b/java/ql/lib/semmle/code/java/frameworks/Jndi.qll index d2b14d5f58e..5d16dc5103a 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Jndi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Jndi.qll @@ -48,18 +48,6 @@ class MethodLdapNameAddAll extends Method { } } -/** - * DEPRECATED: No longer needed as clone steps are handled uniformly. - * - * A method with the name `clone` declared in `javax.naming.ldap.LdapName`. - */ -deprecated class MethodLdapNameClone extends Method { - MethodLdapNameClone() { - this.getDeclaringType() instanceof TypeLdapName and - this.hasName("clone") - } -} - /** A method with the name `getAll` declared in `javax.naming.ldap.LdapName`. */ class MethodLdapNameGetAll extends Method { MethodLdapNameGetAll() { diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index a26e4edc277..3d910485d2f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -156,9 +156,6 @@ class SpringRequestMappingMethod extends SpringControllerMethod { result = this.getProducesExpr().(CompileTimeConstantExpr).getStringValue() } - /** DEPRECATED: Use `getAValue()` instead. */ - deprecated string getValue() { result = requestMappingAnnotation.getStringValue("value") } - /** * Gets a "value" @RequestMapping annotation string value, if present. * diff --git a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll index 81c02e83276..7130e41eeb7 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll @@ -20,13 +20,6 @@ class AndroidNetworkSecurityConfigFile extends XmlFile { } } -/** - * DEPRECATED. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication` instead. - * - * Holds if this database contains an Android manifest file. - */ -deprecated predicate isAndroid() { exists(AndroidManifestXmlFile m) } - /** Holds if the given domain name is trusted by the Network Security Configuration XML file. */ private predicate trustedDomainViaXml(string domainName) { exists( diff --git a/java/ql/lib/semmle/code/java/security/ArithmeticTaintedLocalQuery.qll b/java/ql/lib/semmle/code/java/security/ArithmeticTaintedLocalQuery.qll index 45311174967..f9f98cd93ac 100644 --- a/java/ql/lib/semmle/code/java/security/ArithmeticTaintedLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ArithmeticTaintedLocalQuery.qll @@ -1,49 +1,5 @@ /** Provides taint-tracking configurations to reason about arithmetic using local-user-controlled data. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.security.ArithmeticCommon - -/** - * DEPRECATED: Use `ArithmeticOverflowConfig` instead. - * - * A taint-tracking configuration to reason about arithmetic overflow using local-user-controlled data. - */ -deprecated module ArithmeticTaintedLocalOverflowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { overflowSink(_, sink.asExpr()) } - - predicate isBarrier(DataFlow::Node n) { overflowBarrier(n) } - - predicate isBarrierIn(DataFlow::Node node) { isSource(node) } -} - -/** - * DEPRECATED: Use `ArithmeticOverflow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for arithmetic overflow using local-user-controlled data. - */ -deprecated module ArithmeticTaintedLocalOverflowFlow = - TaintTracking::Global; - -/** - * A taint-tracking configuration to reason about arithmetic underflow using local-user-controlled data. - */ -deprecated module ArithmeticTaintedLocalUnderflowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { underflowSink(_, sink.asExpr()) } - - predicate isBarrier(DataFlow::Node n) { underflowBarrier(n) } - - predicate isBarrierIn(DataFlow::Node node) { isSource(node) } -} - -/** - * DEPRECATED: Use `ArithmeticUnderflow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for arithmetic underflow using local-user-controlled data. - */ -deprecated module ArithmeticTaintedLocalUnderflowFlow = - TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ArithmeticTaintedQuery.qll b/java/ql/lib/semmle/code/java/security/ArithmeticTaintedQuery.qll index 65e73f84149..9d123b379cd 100644 --- a/java/ql/lib/semmle/code/java/security/ArithmeticTaintedQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ArithmeticTaintedQuery.qll @@ -25,11 +25,6 @@ module ArithmeticOverflowConfig implements DataFlow::ConfigSig { } } -/** - * DEPRECATED: Use `ArithmeticOverflowConfig` instead. - */ -deprecated module RemoteUserInputOverflowConfig = ArithmeticOverflowConfig; - /** A taint-tracking configuration to reason about underflow from unvalidated input. */ module ArithmeticUnderflowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource } @@ -51,23 +46,8 @@ module ArithmeticUnderflowConfig implements DataFlow::ConfigSig { } } -/** - * DEPRECATED: Use `ArithmeticUnderflowConfig` instead. - */ -deprecated module RemoteUserInputUnderflowConfig = ArithmeticUnderflowConfig; - /** Taint-tracking flow for overflow from unvalidated input. */ module ArithmeticOverflow = TaintTracking::Global; -/** - * DEPRECATED: Use `ArithmeticOverflow` instead. - */ -deprecated module RemoteUserInputOverflow = ArithmeticOverflow; - /** Taint-tracking flow for underflow from unvalidated input. */ module ArithmeticUnderflow = TaintTracking::Global; - -/** - * DEPRECATED: Use `ArithmeticUnderflow` instead. - */ -deprecated module RemoteUserInputUnderflow = ArithmeticUnderflow; diff --git a/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll b/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll index 273c5360b81..9aa62d950c5 100644 --- a/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll @@ -78,44 +78,11 @@ module InputToArgumentToExecFlowConfig implements DataFlow::ConfigSig { } } -/** - * DEPRECATED: Use `InputToArgumentToExecFlowConfig` instead. - */ -deprecated module RemoteUserInputToArgumentToExecFlowConfig = InputToArgumentToExecFlowConfig; - /** * Taint-tracking flow for unvalidated input that is used to run an external process. */ module InputToArgumentToExecFlow = TaintTracking::Global; -/** - * DEPRECATED: Use `InputToArgumentToExecFlow` instead. - */ -deprecated module RemoteUserInputToArgumentToExecFlow = InputToArgumentToExecFlow; - -/** - * A taint-tracking configuration for unvalidated local user input that is used to run an external process. - */ -deprecated module LocalUserInputToArgumentToExecFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink } - - predicate isBarrier(DataFlow::Node node) { node instanceof CommandInjectionSanitizer } - - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - any(CommandInjectionAdditionalTaintStep s).step(n1, n2) - } -} - -/** - * DEPRECATED: Use `InputToArgumentToExecFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for unvalidated local user input that is used to run an external process. - */ -deprecated module LocalUserInputToArgumentToExecFlow = - TaintTracking::Global; - /** * Implementation of `ExecTainted.ql`. It is extracted to a QLL * so that it can be excluded from `ExecUnescaped.ql` to avoid diff --git a/java/ql/lib/semmle/code/java/security/ExecTaintedLocalQuery.qll b/java/ql/lib/semmle/code/java/security/ExecTaintedLocalQuery.qll index 7a2d5b0947d..dfc727e89d7 100644 --- a/java/ql/lib/semmle/code/java/security/ExecTaintedLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ExecTaintedLocalQuery.qll @@ -1,27 +1,5 @@ /** Provides a taint-tracking configuration to reason about use of externally controlled strings for command injection vulnerabilities. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.security.ExternalProcess -private import semmle.code.java.security.CommandArguments -private import semmle.code.java.security.Sanitizers - -/** A taint-tracking configuration to reason about use of externally controlled strings to make command line commands. */ -deprecated module ExecTaintedLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec } - - predicate isBarrier(DataFlow::Node node) { - node instanceof SimpleTypeSanitizer - or - isSafeCommandArgument(node.asExpr()) - } -} - -/** - * DEPRCATED: Unused. - * - * Taint-tracking flow for use of externally controlled strings to make command line commands. - */ -deprecated module ExecTaintedLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringLocalQuery.qll b/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringLocalQuery.qll index 482673bacc9..79cf2a300f4 100644 --- a/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringLocalQuery.qll @@ -1,26 +1,5 @@ /** Provides a taint-tracking configuration to reason about externally-controlled format strings from local sources. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.StringFormat - -/** A taint-tracking configuration to reason about externally-controlled format strings from local sources. */ -deprecated module ExternallyControlledFormatStringLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(StringFormat formatCall).getFormatArgument() - } - - predicate isBarrier(DataFlow::Node node) { - node.getType() instanceof NumericType or node.getType() instanceof BooleanType - } -} - -/** - * DEPRECATED: Use `ExternallyControlledFormatStringFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for externally-controlled format strings from local sources. - */ -deprecated module ExternallyControlledFormatStringLocalFlow = - TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayConstructionLocalQuery.qll b/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayConstructionLocalQuery.qll index 1d31d7afb87..e5b51c2ae53 100644 --- a/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayConstructionLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayConstructionLocalQuery.qll @@ -1,24 +1,5 @@ /** Provides a taint-tracking configuration to reason about improper validation of local user-provided size used for array construction. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.security.internal.ArraySizing -private import semmle.code.java.dataflow.FlowSources - -/** - * A taint-tracking configuration to reason about improper validation of local user-provided size used for array construction. - */ -deprecated module ImproperValidationOfArrayConstructionLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { - any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _) - } -} - -/** - * DEPRECATED: Use `ImproperValidationOfArrayConstructionFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for improper validation of local user-provided size used for array construction. - */ -deprecated module ImproperValidationOfArrayConstructionLocalFlow = - TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayIndexLocalQuery.qll b/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayIndexLocalQuery.qll index 5f1e7c81e01..b6b1366fb40 100644 --- a/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayIndexLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ImproperValidationOfArrayIndexLocalQuery.qll @@ -1,28 +1,5 @@ /** Provides a taint-tracking configuration to reason about improper validation of local user-provided array index. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.security.internal.ArraySizing -private import semmle.code.java.dataflow.FlowSources - -/** - * A taint-tracking configuration to reason about improper validation of local user-provided array index. - */ -deprecated module ImproperValidationOfArrayIndexLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { - any(CheckableArrayAccess caa).canThrowOutOfBounds(sink.asExpr()) - } - - predicate isBarrier(DataFlow::Node node) { node.getType() instanceof BooleanType } - - predicate isBarrierIn(DataFlow::Node node) { isSource(node) } -} - -/** - * DEPRECATED: Use `ImproperValidationOfArrayIndexFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for improper validation of local user-provided array index. - */ -deprecated module ImproperValidationOfArrayIndexLocalFlow = - TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/NumericCastTaintedQuery.qll b/java/ql/lib/semmle/code/java/security/NumericCastTaintedQuery.qll index 793871a4bd2..a4c3785feea 100644 --- a/java/ql/lib/semmle/code/java/security/NumericCastTaintedQuery.qll +++ b/java/ql/lib/semmle/code/java/security/NumericCastTaintedQuery.qll @@ -115,34 +115,3 @@ module NumericCastFlowConfig implements DataFlow::ConfigSig { * Taint-tracking flow for user input that is used in a numeric cast. */ module NumericCastFlow = TaintTracking::Global; - -/** - * A taint-tracking configuration for reasoning about local user input that is - * used in a numeric cast. - */ -deprecated module NumericCastLocalFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr() and - sink.asExpr() instanceof VarAccess - } - - predicate isBarrier(DataFlow::Node node) { - boundedRead(node.asExpr()) or - castCheck(node.asExpr()) or - node.getType() instanceof SmallType or - smallExpr(node.asExpr()) or - node.getEnclosingCallable() instanceof HashCodeMethod or - exists(RightShiftOp e | e.getShiftedVariable().getAnAccess() = node.asExpr()) - } - - predicate isBarrierIn(DataFlow::Node node) { isSource(node) } -} - -/** - * DEPRECATED: Use `NumericCastFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for local user input that is used in a numeric cast. - */ -deprecated module NumericCastLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ResponseSplittingLocalQuery.qll b/java/ql/lib/semmle/code/java/security/ResponseSplittingLocalQuery.qll index e5845b630ec..e0383cd52d9 100644 --- a/java/ql/lib/semmle/code/java/security/ResponseSplittingLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ResponseSplittingLocalQuery.qll @@ -1,39 +1,5 @@ /** Provides a taint-tracking configuration to reason about response splitting vulnerabilities from local user input. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.security.ResponseSplitting - -/** - * A taint-tracking configuration to reason about response splitting vulnerabilities from local user input. - */ -deprecated module ResponseSplittingLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } - - predicate isBarrier(DataFlow::Node node) { - node.getType() instanceof PrimitiveType - or - node.getType() instanceof BoxedType - or - exists(MethodCall ma, string methodName, CompileTimeConstantExpr target | - node.asExpr() = ma and - ma.getMethod().hasQualifiedName("java.lang", "String", methodName) and - target = ma.getArgument(0) and - ( - methodName = "replace" and target.getIntValue() = [10, 13] // 10 == "\n", 13 == "\r" - or - methodName = "replaceAll" and - target.getStringValue().regexpMatch(".*([\n\r]|\\[\\^[^\\]\r\n]*\\]).*") - ) - ) - } -} - -/** - * DEPRECATED: Use `ResponseSplittingFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for response splitting vulnerabilities from local user input. - */ -deprecated module ResponseSplittingLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/SqlTaintedLocalQuery.qll b/java/ql/lib/semmle/code/java/security/SqlTaintedLocalQuery.qll index 7ff4b300ce8..80cd491acf2 100644 --- a/java/ql/lib/semmle/code/java/security/SqlTaintedLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SqlTaintedLocalQuery.qll @@ -2,32 +2,7 @@ * Provides a taint-tracking configuration for reasoning about local user input * that is used in a SQL query. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.security.SqlInjectionQuery -private import semmle.code.java.security.Sanitizers - -/** - * A taint-tracking configuration for reasoning about local user input that is - * used in a SQL query. - */ -deprecated module LocalUserInputToQueryInjectionFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink } - - predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - any(AdditionalQueryInjectionTaintStep s).step(node1, node2) - } -} - -/** - * DEPRECATED: Use `QueryInjectionFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for local user input that is used in a SQL query. - */ -deprecated module LocalUserInputToQueryInjectionFlow = - TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 6726bcc3508..27b65e7eae0 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -78,28 +78,3 @@ module TaintedPathConfig implements DataFlow::ConfigSig { /** Tracks flow from remote sources to the creation of a path. */ module TaintedPathFlow = TaintTracking::Global; - -/** - * A taint-tracking configuration for tracking flow from local user input to the creation of a path. - */ -deprecated module TaintedPathLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof TaintedPathSink } - - predicate isBarrier(DataFlow::Node sanitizer) { - sanitizer instanceof SimpleTypeSanitizer or - sanitizer instanceof PathInjectionSanitizer - } - - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - any(TaintedPathAdditionalTaintStep s).step(n1, n2) - } -} - -/** - * DEPRECATED: Use `TaintedPathFlow` instead and configure threat model sources to include `local`. - * - * Tracks flow from local user input to the creation of a path. - */ -deprecated module TaintedPathLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/UrlRedirectLocalQuery.qll b/java/ql/lib/semmle/code/java/security/UrlRedirectLocalQuery.qll index f68fb959ea5..2016e9be14f 100644 --- a/java/ql/lib/semmle/code/java/security/UrlRedirectLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UrlRedirectLocalQuery.qll @@ -1,21 +1,5 @@ /** Provides a taint-tracking configuration to reason about URL redirection from local sources. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.security.UrlRedirect - -/** - * A taint-tracking configuration to reason about URL redirection from local sources. - */ -deprecated module UrlRedirectLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof UrlRedirectSink } -} - -/** - * DEPRECATED: Use `UrlRedirectFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for URL redirection from local sources. - */ -deprecated module UrlRedirectLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/XssLocalQuery.qll b/java/ql/lib/semmle/code/java/security/XssLocalQuery.qll index 5e1098865aa..fd8fd6f451c 100644 --- a/java/ql/lib/semmle/code/java/security/XssLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XssLocalQuery.qll @@ -1,30 +1,5 @@ /** Provides a taint-tracking configuration to reason about cross-site scripting from a local source. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.dataflow.TaintTracking -private import semmle.code.java.security.XSS - -/** - * A taint-tracking configuration for reasoning about cross-site scripting vulnerabilities from a local source. - */ -deprecated module XssLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof XssSink } - - predicate isBarrier(DataFlow::Node node) { node instanceof XssSanitizer } - - predicate isBarrierOut(DataFlow::Node node) { node instanceof XssSinkBarrier } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - any(XssAdditionalTaintStep s).step(node1, node2) - } -} - -/** - * DEPRECATED: Use `XssFlow` instead and configure threat model sources to include `local`. - * - * Taint-tracking flow for cross-site scripting vulnerabilities from a local source. - */ -deprecated module XssLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll b/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll index f485137fc78..c45cd560cfc 100644 --- a/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll @@ -1,28 +1,5 @@ /** Provides taint tracking configurations to be used in local XXE queries. */ +overlay[local?] +deprecated module; import java -private import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.dataflow.TaintTracking -private import semmle.code.java.security.XxeQuery - -/** - * A taint-tracking configuration for unvalidated local user input that is used in XML external entity expansion. - */ -deprecated module XxeLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { sink instanceof XxeSink } - - predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof XxeSanitizer } - - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - any(XxeAdditionalTaintStep s).step(n1, n2) - } -} - -/** - * DEPRECATED: Use `XxeFlow` instead and configure threat model sources to include `local`. - * - * Detect taint flow of unvalidated local user input that is used in XML external entity expansion. - */ -deprecated module XxeLocalFlow = TaintTracking::Global; diff --git a/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll b/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll deleted file mode 100644 index 5d047f1e82a..00000000000 --- a/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Provides classes for working with MyBatis mapper xml files and their content. - */ -deprecated module; - -import java - -/** - * MyBatis Mapper XML file. - */ -class MyBatisMapperXmlFile extends XmlFile { - MyBatisMapperXmlFile() { - count(XmlElement e | e = this.getAChild()) = 1 and - this.getAChild().getName() = "mapper" - } -} - -/** - * An XML element in a `MyBatisMapperXMLFile`. - */ -class MyBatisMapperXmlElement extends XmlElement { - MyBatisMapperXmlElement() { this.getFile() instanceof MyBatisMapperXmlFile } - - /** - * Gets the value for this element, with leading and trailing whitespace trimmed. - */ - string getValue() { result = this.allCharactersString().trim() } - - /** - * Gets the reference type bound to MyBatis Mapper XML File. - */ - RefType getNamespaceRefType() { - result.getQualifiedName() = this.getAttribute("namespace").getValue() - } -} - -/** - * An MyBatis Mapper sql operation element. - */ -abstract class MyBatisMapperSqlOperation extends MyBatisMapperXmlElement { - /** - * Gets the value of the `id` attribute of MyBatis Mapper sql operation element. - */ - string getId() { result = this.getAttribute("id").getValue() } - - /** - * Gets the `` element in a `MyBatisMapperSqlOperation`. - */ - MyBatisMapperInclude getInclude() { result = this.getAChild*() } - - /** - * Gets the method bound to MyBatis Mapper XML File. - */ - Method getMapperMethod() { - result.getName() = this.getId() and - result.getDeclaringType() = this.getParent().(MyBatisMapperXmlElement).getNamespaceRefType() - } -} - -/** - * A `` element in a `MyBatisMapperSqlOperation`. - */ -class MyBatisMapperInsert extends MyBatisMapperSqlOperation { - MyBatisMapperInsert() { this.getName() = "insert" } -} - -/** - * A `` element in a `MyBatisMapperSqlOperation`. - */ -class MyBatisMapperUpdate extends MyBatisMapperSqlOperation { - MyBatisMapperUpdate() { this.getName() = "update" } -} - -/** - * A `` element in a `MyBatisMapperSqlOperation`. - */ -class MyBatisMapperDelete extends MyBatisMapperSqlOperation { - MyBatisMapperDelete() { this.getName() = "delete" } -} - -/** - * A `