How does Semgrep handle two conflicting Typed Metavariable classes? - semgrep

Semgrep allows you to specify types in your patterns, but if I happen to have two different classes with the same simple type, but a different fully qualified name, how can I disambiguate between the two when writing a rule where I only want to target one of those types?
I'll explain my question through example. Say you have two different libraries that both have the same class name Foo.
In one file of my own code I import one library, and use the Foo class:
import lib1.* // has Foo class
f = Foo()
f.bar()
In another file of my own code, I import the other library and use it’s Foo class:
import lib2.* // has different Foo class
f2 = Foo()
f2.baz()
In my Semgrep rule, I want to detect things of type Foo from lib1.
pattern: (Foo $F)
Since my pattern doesn’t know anything about imports, does it just return results from both files?

Yes, since your pattern only specifies type Foo, Semgrep will return both f1 and f2 as matches. If you want to match only one of those, you can specify the fully qualified name of the type you want to match:
pattern: (lib1.Foo $F)

Related

Predicate-Polymorphic Modules in Alloy?

In alloy you can make modules polymorphic on signatures by defining them as arguments in the module definition, e.g.:
module mymodule[sigA,sigB]
In my case, I also want to have predicates about these signatures that might change in the different instantiations of my module. Something like, say,
module mymodule[sigA,predA]
sig B extends sigA {}
pred B[b : B] { ... }
fact { all b : B | predA[b] => predB[b]}
If I just do it like this naively, Alloy complains that it won't typecheck, as parameters to a module are automatically assumed to be signatures. Is there any workaround or some other way to make modules be polymorphic in predicates like this?
Genericity in the module system is indeed limited to signatures parameters. The only workaround (sort of) I know of is exemplified in util/graph for instance, of which I'm pasting an excerpt:
module util/graph[node]
/** graph is rooted at root */
pred rootedAt[r: node->node, root: node] {
node in root.*r
}
As you can see, node is a parameter. If you want to talk about a relation on nodes, then you pass it as a parameter (e.g.: rootedAt). So, you can;t require the existence of a relation on nodes, in addition to the signature node itself, but you can give the module "client" means to reason about fields too.

Kotlin: Prevent mixup of same typed parameters

How can I save the cats from being served for dinner?
data class Animal(
val name: String
)
data class ToDo(
val toEat: List<Animal>,
val toFeed: List<Animal>,
)
val cats = listOf(Animal("fluffy"))
val chickens = listOf(Animal("chic"))
// help the kittens!!!
ToDo(cats, chickens)
Note: This is a simplified example and I cant change the Type of cats/chickens to something like Cat/Chicken.
OOP solution
You could do the following:
Animal should be an interface.
Cat and Chicken should be two different implementation of Animal.
You could define an Interface named Eatable which will have concrete implementations.
Change val toEat: List<Animal> in val toEat: List<Eatable>
Cat will implement Animal and not Eatable
Another solution
Sorry but i read just now that you cannot define 2 different classes for Cat and Chicken.
You should still define this in Animal (pseudocode):
boolean eatable = false;
fun isEatable(): boolean {
return eatable;
}
So you can define Animal.eat(Animal) to check if the animal you are trying to eat could be eaten.
If you can't give them different types, then I don't think there's any way the compiler could spot this problem.  However, you could make it more obvious by simply giving the parameter names:
ToDo(toEat = chickens, toFeed = cats)
That way, it's very clear which list goes with which parameter.  (It also means that the order of the parameters doesn't matter; you can swap them, as long as each is given once.)
It would still compile if you mixed them up:
ToDo(toEat = cats, toFeed = chickens)
…but at least that would be obvious and doesn't need you to check the documentation to see the problem.
A caller could still choose to omit the parameter names, though.  To prevent that, you'd have to restructure the ToDo class.  For example, you could use the builder pattern, and give something like:
ToDo().toEat(chickens).toFeed(cats)
Or you could simply remove the parameters from the constructor, requiring the caller to set properties by name, e.g.:
ToDo().apply{ toEat = chickens; toFeed = cats }
Those are a little more long-winded to call, of course, but force the caller to give the property names explicitly — again, making the problem fairly obvious to human readers (if not to the compiler).

Can Raku's introspection list all the multi candidates across different files/Modules?

When a proto and multis are defined in the same module, Type.^lookup('method').candidates returns a list of all multi candidates. However, this appears not to work when the proto lives in a different file/module from the multis.
say Setty.^lookup('grab').candidates; # OUTPUT: ()
Is there any way to find the full list of multi candidates through Raku's introspection? Or is there no alternative to grepping through the source code? (I ask because having a full list of multi candidates applicable to a given proto would be helpful for documentation purposes.)
So far as multi methods go, it's not really to do with being in the same module or file at all. Consider these classes:
class Base {
proto method m(|) { * }
multi method m() { 1 }
}
class Derived is Base {
multi method m() { 2 }
}
Whenever we compose a class that contains multi methods, we need to attach them to a controlling proto. In the case of Base, this was explicitly written, so there's nothing to do other than to add the multi candidate to its candidate list. Had we not written a proto explicitly in Base, however, then one with an empty candidate list would have been generated for us, with the same end result.
The process I just described is a bit of a simplification of what really happens, however. The steps are:
See if this class has a proto already; if so, add the multi to it
Otherwise, see if any base class has a proto; if so, clone it (in tern cloning the candidate list) and add the multi to that.
Otherwise, generate a new proto.
And step 2 is really the answer to your question. If we do:
say "Base:";
.raku.say for Base.^lookup('m').candidates;
say "Derived:";
.raku.say for Derived.^lookup('m').candidates;
Then the output is:
Base:
multi method m (Base: *%_) { #`(Method|82762064) ... }
Derived:
multi method m (Base: ) { #`(Method|82762064) ... }
multi method m (Derived: ) { #`(Method|82762208) ... }
That is, the candidate list in Base has one entry, and the candidate list in Derived has the entry cloned from Base as well as a new one.
Pretty much everything follows this principle: derived classes reference their base class (and the roles they do), but base classes (and roles) don't know about their descendants.

Using Polymorphism instead of Switch

Here is the logic:
The server prepares the file (like index.html, or some.pdf) that it is going to send through HTTP response. Based on the suffix I wanna set the Content-type in HTTP header.
The logic now is I have Class Filetype, with lots of specific filetype subclasses extending it. But still I need to use "switch" to identify the suffix. Something like:
Filetype f = null;
if(suffix == "pdf"){
f = Filetype_pdf(source);
} else if (suffix == "html") {
f = Filetype_text(source);
}
But I use inheritance just to avoid these "if"s. Any advice to this issue or is this the way it should be? Thanks.
Let's say that you have the following hierarchy:
Filetype
HTMLType
PDFType
TxtType
Now assume that each of these classes understands the type message (not their instances, the class). Then you can create a class method in Filetype namely classFor that receives one argument extension and responds the subclass of Filetype that handles that extension. The implementation of classFor consists in enumerating all the subclasses looking for the subclass whose type matches extension.
In Smalltalk this would look like
classFor: extension
^Filetype allSubclasses detect: [:cls | cls type = extension]
Of course, there is an if message somewhere in the implementation of detect, but your code does not see it and elegantly expresses the condition that must be met.
EDIT:
The beauty if this approach is that the method classFor that detects the appropriate subclass will not change if you add (or remove) other subclasses that support new types of files. This contrasts with the switch statement that must name all the possibilities exhaustively. By avoiding the switch your code acquires the generality required to keep working with newer versions of your hierarchy.

Generators for regular classes in scalacheck

In scalacheck's user guide there is "Generating Case Classes" paragraph. I modified example from it to use regular classes instead of case classes:
import org.scalacheck._
import Gen._
import Arbitrary._
sealed abstract class Tree
object Leaf extends Tree
class Node(left:Tree, rigth:Tree, v:Int) extends Tree
object Main {
val genLeaf = value(Leaf)
val genNode = for{
v <- Arbitrary.arbitrary[Int]
left <- genTree
rigth <- genTree
} yield new Node(left, rigth, v)
val genTree:Gen[Tree] = oneOf(genLeaf, genNode)
def main(args:Array[String]){
println(genTree.sample)
}
}
It seems everything working but I'm afraid of using this approach in production code before I ask here: is there any pitfalls?
This should work fine. There's nothing about case classes that are particularly magical about case classes as far as ScalaCheck is concerned. Any old class can get a generator, or even be convertible to Arbitrary.
As far as testing goes, one difference is that every non-case-class tree you generate will be unique, and thus for no two trees you generate will tree1 == tree2. That's different from how it is with case class, which test equality based on value rather than identity. You may need more tests to handle issues with aliasing that become possible when you have identity-based rather than value-based equality.
I see no problem here. The reason why case classes are used in that example is that the Tree shown is an algebraic data type, made possible with case classes. With normal classes, you cannot pattern match on the tree, and, in fact, you won't even be able to get left, right and v without declaring them val.