[analyzer]

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[analyzer]

via cfe-dev

Hello. I am newbie in Clang Static Analyzer and I am trying to write new Clang Static Analyzer check, which is aimed to find issues with casting values to enum: if we cast anything which is no presented in target enum it will be unspecified/undefined behavior(depends on C++ version).

So my plan is:

  1. Find all casts in source code. Seems like 'check::PreStmt<CastExpr>>' it's what I need.
  2. In my implementation of `checkPreStmt` method I must get target type from CastExpr, but I don't know, how to do it - can you help with it?
  3. Then if target type in Cast is Enum, I must get all values from this Enum and compare it with all possible values which can be presented by CastExpr->getSubExpr() - here I don't know how to evaluate CastExpr->getSubExpr() and how to get all values from Enum.

Do you have any ideas?

-- 
Best regards,
Alexander Zaitsev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer]

via cfe-dev
Hi,

Your overall plan sounds good, and i believe that such checker will be
very useful, i'd love to have such check in the analyzer. If you want to
post it upstream, i encourage you to start early by publishing
prototypes on Phabricator for code reviews, even when you think they're
not ready, just because code reviews are cool!

Path-sensitive analysis is indeed useful here because sometimes it's not
immediately obvious from the code which values are possible for the
sub-expression. Defining the buggy state can be a bit annoying because
enum values can be non-contiguous and/or numerous; the former means that
you'll potentially need to make a lot of State->assume(...) calls and
see if none of the states with assumptions are null; the latter means
that you'll need to make sure you identify segments of values to avoid
calling assume() for *every* enum item. I also recommend
ConstraintManager::assumeInclusiveRange() for direct assumptions over
segments.

Your questions so far are AST questions, not specific to the analyzer.
First of all, notice that every expression has a (qualified) type, which
is the type of the value it evaluates to, and it can always be obtained
via Expr::getType(). It may be void (eg., call expression for a function
that returns void), but it's always there.

For cast-expression, as you might have already guessed, the type of the
expression is the target type of the cast. Because, well, that's the
whole point of the cast. This takes care of question 2.

Most functions return not raw Types but QualType objects that are types
with qualifiers. You can always use the overloaded operator->() on the
QualType to access the underlying Type; there's also
QualType::getTypePtr(), but if you think you need it - most likely you
don't.

Now, types, like statements or declarations, are a hierarchy. Some types
are integer types, some are array or structure types, some are enum
types. Enum types are represented by the EnumType class, to which you
can try to dyn_cast<>() your type. Or, even better, use Type::getAs<>(),
which can be accessed directly with operator->() on QualType.

If dyn_cast<>()/getAs<>() is successful - your type is an enum and you
have a pointer to an EnumType object, so you can call
EnumType::getDecl() to find the *declaration* of the enum in the code.

Also if the enum hides under a typedef, then the type wouldn't be an
EnumType but it'd be a TypedefType, so the cast would fail. The easy way
to get rid of typedefs is to do QualType::getCanonicalType().

Some declarations are forward declarations. You might need to do
EnumDecl::getDefinition() to find the actual definition. Maybe you don't
need that: i don't remember what operations are allowed on incomplete
enum types.

Once you have your EnumDecl that is the definition, you can iterate over
EnumDecl::enumerators() to see what values are present.

In Clang there are a lot more cast kinds of expressions than you
probably expect, so you might want to take a look at the list of casts
in clang/AST/OperationKinds.def and see which ones do you need; i don't
think it'll be important at first, but just in case.

In order to quickly catch up on the basics, i also recommend the AST
tutorial by Manuel Klimek at https://www.youtube.com/watch?v=VqCkCDFLSsc


On 10/24/18 5:16 PM, Alexander Zaitsev via cfe-dev wrote:

>
> Hello. I am newbie in Clang Static Analyzer and I am trying to write
> new Clang Static Analyzer check, which is aimed to find issues with
> casting values to enum: if we cast anything which is no presented in
> target enum it will be unspecified/undefined behavior(depends on C++
> version).
>
> So my plan is:
>
>  1. Find all casts in source code. Seems like
>     'check::PreStmt<CastExpr>>' it's what I need.
>  2. In my implementation of `checkPreStmt` method I must get target
>     type from CastExpr, but I don't know, how to do it - can you help
>     with it?
>  3. Then if target type in Cast is Enum, I must get all values from
>     this Enum and compare it with all possible values which can be
>     presented by CastExpr->getSubExpr() - here I don't know how to
>     evaluate CastExpr->getSubExpr() and how to get all values from Enum.
>
> Do you have any ideas?
>
> --
> Best regards,
> Alexander Zaitsev
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer]

via cfe-dev
Hi!

Do you have something in mind like this: https://reviews.llvm.org/D33672 ?

Regards,
Gábor

Artem Dergachev via cfe-dev <[hidden email]> ezt írta (időpont: 2018. okt. 25., Cs 4:32):
Hi,

Your overall plan sounds good, and i believe that such checker will be
very useful, i'd love to have such check in the analyzer. If you want to
post it upstream, i encourage you to start early by publishing
prototypes on Phabricator for code reviews, even when you think they're
not ready, just because code reviews are cool!

Path-sensitive analysis is indeed useful here because sometimes it's not
immediately obvious from the code which values are possible for the
sub-expression. Defining the buggy state can be a bit annoying because
enum values can be non-contiguous and/or numerous; the former means that
you'll potentially need to make a lot of State->assume(...) calls and
see if none of the states with assumptions are null; the latter means
that you'll need to make sure you identify segments of values to avoid
calling assume() for *every* enum item. I also recommend
ConstraintManager::assumeInclusiveRange() for direct assumptions over
segments.

Your questions so far are AST questions, not specific to the analyzer.
First of all, notice that every expression has a (qualified) type, which
is the type of the value it evaluates to, and it can always be obtained
via Expr::getType(). It may be void (eg., call expression for a function
that returns void), but it's always there.

For cast-expression, as you might have already guessed, the type of the
expression is the target type of the cast. Because, well, that's the
whole point of the cast. This takes care of question 2.

Most functions return not raw Types but QualType objects that are types
with qualifiers. You can always use the overloaded operator->() on the
QualType to access the underlying Type; there's also
QualType::getTypePtr(), but if you think you need it - most likely you
don't.

Now, types, like statements or declarations, are a hierarchy. Some types
are integer types, some are array or structure types, some are enum
types. Enum types are represented by the EnumType class, to which you
can try to dyn_cast<>() your type. Or, even better, use Type::getAs<>(),
which can be accessed directly with operator->() on QualType.

If dyn_cast<>()/getAs<>() is successful - your type is an enum and you
have a pointer to an EnumType object, so you can call
EnumType::getDecl() to find the *declaration* of the enum in the code.

Also if the enum hides under a typedef, then the type wouldn't be an
EnumType but it'd be a TypedefType, so the cast would fail. The easy way
to get rid of typedefs is to do QualType::getCanonicalType().

Some declarations are forward declarations. You might need to do
EnumDecl::getDefinition() to find the actual definition. Maybe you don't
need that: i don't remember what operations are allowed on incomplete
enum types.

Once you have your EnumDecl that is the definition, you can iterate over
EnumDecl::enumerators() to see what values are present.

In Clang there are a lot more cast kinds of expressions than you
probably expect, so you might want to take a look at the list of casts
in clang/AST/OperationKinds.def and see which ones do you need; i don't
think it'll be important at first, but just in case.

In order to quickly catch up on the basics, i also recommend the AST
tutorial by Manuel Klimek at https://www.youtube.com/watch?v=VqCkCDFLSsc


On 10/24/18 5:16 PM, Alexander Zaitsev via cfe-dev wrote:
>
> Hello. I am newbie in Clang Static Analyzer and I am trying to write
> new Clang Static Analyzer check, which is aimed to find issues with
> casting values to enum: if we cast anything which is no presented in
> target enum it will be unspecified/undefined behavior(depends on C++
> version).
>
> So my plan is:
>
>  1. Find all casts in source code. Seems like
>     'check::PreStmt<CastExpr>>' it's what I need.
>  2. In my implementation of `checkPreStmt` method I must get target
>     type from CastExpr, but I don't know, how to do it - can you help
>     with it?
>  3. Then if target type in Cast is Enum, I must get all values from
>     this Enum and compare it with all possible values which can be
>     presented by CastExpr->getSubExpr() - here I don't know how to
>     evaluate CastExpr->getSubExpr() and how to get all values from Enum.
>
> Do you have any ideas?
>
> --
> Best regards,
> Alexander Zaitsev
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer]

via cfe-dev

Didn't know that this check is already implemented. I think I can continue this work (seems like original author of the change don't work on it now). What do you think?

25.10.2018 6:34, Gábor Horváth пишет:
Hi!

Do you have something in mind like this: https://reviews.llvm.org/D33672 ?

Regards,
Gábor

Artem Dergachev via cfe-dev <[hidden email]> ezt írta (időpont: 2018. okt. 25., Cs 4:32):
Hi,

Your overall plan sounds good, and i believe that such checker will be
very useful, i'd love to have such check in the analyzer. If you want to
post it upstream, i encourage you to start early by publishing
prototypes on Phabricator for code reviews, even when you think they're
not ready, just because code reviews are cool!

Path-sensitive analysis is indeed useful here because sometimes it's not
immediately obvious from the code which values are possible for the
sub-expression. Defining the buggy state can be a bit annoying because
enum values can be non-contiguous and/or numerous; the former means that
you'll potentially need to make a lot of State->assume(...) calls and
see if none of the states with assumptions are null; the latter means
that you'll need to make sure you identify segments of values to avoid
calling assume() for *every* enum item. I also recommend
ConstraintManager::assumeInclusiveRange() for direct assumptions over
segments.

Your questions so far are AST questions, not specific to the analyzer.
First of all, notice that every expression has a (qualified) type, which
is the type of the value it evaluates to, and it can always be obtained
via Expr::getType(). It may be void (eg., call expression for a function
that returns void), but it's always there.

For cast-expression, as you might have already guessed, the type of the
expression is the target type of the cast. Because, well, that's the
whole point of the cast. This takes care of question 2.

Most functions return not raw Types but QualType objects that are types
with qualifiers. You can always use the overloaded operator->() on the
QualType to access the underlying Type; there's also
QualType::getTypePtr(), but if you think you need it - most likely you
don't.

Now, types, like statements or declarations, are a hierarchy. Some types
are integer types, some are array or structure types, some are enum
types. Enum types are represented by the EnumType class, to which you
can try to dyn_cast<>() your type. Or, even better, use Type::getAs<>(),
which can be accessed directly with operator->() on QualType.

If dyn_cast<>()/getAs<>() is successful - your type is an enum and you
have a pointer to an EnumType object, so you can call
EnumType::getDecl() to find the *declaration* of the enum in the code.

Also if the enum hides under a typedef, then the type wouldn't be an
EnumType but it'd be a TypedefType, so the cast would fail. The easy way
to get rid of typedefs is to do QualType::getCanonicalType().

Some declarations are forward declarations. You might need to do
EnumDecl::getDefinition() to find the actual definition. Maybe you don't
need that: i don't remember what operations are allowed on incomplete
enum types.

Once you have your EnumDecl that is the definition, you can iterate over
EnumDecl::enumerators() to see what values are present.

In Clang there are a lot more cast kinds of expressions than you
probably expect, so you might want to take a look at the list of casts
in clang/AST/OperationKinds.def and see which ones do you need; i don't
think it'll be important at first, but just in case.

In order to quickly catch up on the basics, i also recommend the AST
tutorial by Manuel Klimek at https://www.youtube.com/watch?v=VqCkCDFLSsc


On 10/24/18 5:16 PM, Alexander Zaitsev via cfe-dev wrote:
>
> Hello. I am newbie in Clang Static Analyzer and I am trying to write
> new Clang Static Analyzer check, which is aimed to find issues with
> casting values to enum: if we cast anything which is no presented in
> target enum it will be unspecified/undefined behavior(depends on C++
> version).
>
> So my plan is:
>
>  1. Find all casts in source code. Seems like
>     'check::PreStmt<CastExpr>>' it's what I need.
>  2. In my implementation of `checkPreStmt` method I must get target
>     type from CastExpr, but I don't know, how to do it - can you help
>     with it?
>  3. Then if target type in Cast is Enum, I must get all values from
>     this Enum and compare it with all possible values which can be
>     presented by CastExpr->getSubExpr() - here I don't know how to
>     evaluate CastExpr->getSubExpr() and how to get all values from Enum.
>
> Do you have any ideas?
>
> --
> Best regards,
> Alexander Zaitsev
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-- 
Best regards,
Alexander Zaitsev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer]

via cfe-dev
Given the lack of recent activity feel free to commandeer the revision. I think it should be quite close to be merged.

On Thu, 25 Oct 2018 at 10:30, Alexander Zaitsev <[hidden email]> wrote:

Didn't know that this check is already implemented. I think I can continue this work (seems like original author of the change don't work on it now). What do you think?

25.10.2018 6:34, Gábor Horváth пишет:
Hi!

Do you have something in mind like this: https://reviews.llvm.org/D33672 ?

Regards,
Gábor

Artem Dergachev via cfe-dev <[hidden email]> ezt írta (időpont: 2018. okt. 25., Cs 4:32):
Hi,

Your overall plan sounds good, and i believe that such checker will be
very useful, i'd love to have such check in the analyzer. If you want to
post it upstream, i encourage you to start early by publishing
prototypes on Phabricator for code reviews, even when you think they're
not ready, just because code reviews are cool!

Path-sensitive analysis is indeed useful here because sometimes it's not
immediately obvious from the code which values are possible for the
sub-expression. Defining the buggy state can be a bit annoying because
enum values can be non-contiguous and/or numerous; the former means that
you'll potentially need to make a lot of State->assume(...) calls and
see if none of the states with assumptions are null; the latter means
that you'll need to make sure you identify segments of values to avoid
calling assume() for *every* enum item. I also recommend
ConstraintManager::assumeInclusiveRange() for direct assumptions over
segments.

Your questions so far are AST questions, not specific to the analyzer.
First of all, notice that every expression has a (qualified) type, which
is the type of the value it evaluates to, and it can always be obtained
via Expr::getType(). It may be void (eg., call expression for a function
that returns void), but it's always there.

For cast-expression, as you might have already guessed, the type of the
expression is the target type of the cast. Because, well, that's the
whole point of the cast. This takes care of question 2.

Most functions return not raw Types but QualType objects that are types
with qualifiers. You can always use the overloaded operator->() on the
QualType to access the underlying Type; there's also
QualType::getTypePtr(), but if you think you need it - most likely you
don't.

Now, types, like statements or declarations, are a hierarchy. Some types
are integer types, some are array or structure types, some are enum
types. Enum types are represented by the EnumType class, to which you
can try to dyn_cast<>() your type. Or, even better, use Type::getAs<>(),
which can be accessed directly with operator->() on QualType.

If dyn_cast<>()/getAs<>() is successful - your type is an enum and you
have a pointer to an EnumType object, so you can call
EnumType::getDecl() to find the *declaration* of the enum in the code.

Also if the enum hides under a typedef, then the type wouldn't be an
EnumType but it'd be a TypedefType, so the cast would fail. The easy way
to get rid of typedefs is to do QualType::getCanonicalType().

Some declarations are forward declarations. You might need to do
EnumDecl::getDefinition() to find the actual definition. Maybe you don't
need that: i don't remember what operations are allowed on incomplete
enum types.

Once you have your EnumDecl that is the definition, you can iterate over
EnumDecl::enumerators() to see what values are present.

In Clang there are a lot more cast kinds of expressions than you
probably expect, so you might want to take a look at the list of casts
in clang/AST/OperationKinds.def and see which ones do you need; i don't
think it'll be important at first, but just in case.

In order to quickly catch up on the basics, i also recommend the AST
tutorial by Manuel Klimek at https://www.youtube.com/watch?v=VqCkCDFLSsc


On 10/24/18 5:16 PM, Alexander Zaitsev via cfe-dev wrote:
>
> Hello. I am newbie in Clang Static Analyzer and I am trying to write
> new Clang Static Analyzer check, which is aimed to find issues with
> casting values to enum: if we cast anything which is no presented in
> target enum it will be unspecified/undefined behavior(depends on C++
> version).
>
> So my plan is:
>
>  1. Find all casts in source code. Seems like
>     'check::PreStmt<CastExpr>>' it's what I need.
>  2. In my implementation of `checkPreStmt` method I must get target
>     type from CastExpr, but I don't know, how to do it - can you help
>     with it?
>  3. Then if target type in Cast is Enum, I must get all values from
>     this Enum and compare it with all possible values which can be
>     presented by CastExpr->getSubExpr() - here I don't know how to
>     evaluate CastExpr->getSubExpr() and how to get all values from Enum.
>
> Do you have any ideas?
>
> --
> Best regards,
> Alexander Zaitsev
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-- 
Best regards,
Alexander Zaitsev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer]

via cfe-dev
Ah, my memory of a surgeonfish never fails me.
Yeah, i guess just take it over.

On 10/25/18 2:55 AM, Gábor Horváth wrote:
Given the lack of recent activity feel free to commandeer the revision. I think it should be quite close to be merged.

On Thu, 25 Oct 2018 at 10:30, Alexander Zaitsev <[hidden email]> wrote:

Didn't know that this check is already implemented. I think I can continue this work (seems like original author of the change don't work on it now). What do you think?

25.10.2018 6:34, Gábor Horváth пишет:
Hi!

Do you have something in mind like this: https://reviews.llvm.org/D33672 ?

Regards,
Gábor

Artem Dergachev via cfe-dev <[hidden email]> ezt írta (időpont: 2018. okt. 25., Cs 4:32):
Hi,

Your overall plan sounds good, and i believe that such checker will be
very useful, i'd love to have such check in the analyzer. If you want to
post it upstream, i encourage you to start early by publishing
prototypes on Phabricator for code reviews, even when you think they're
not ready, just because code reviews are cool!

Path-sensitive analysis is indeed useful here because sometimes it's not
immediately obvious from the code which values are possible for the
sub-expression. Defining the buggy state can be a bit annoying because
enum values can be non-contiguous and/or numerous; the former means that
you'll potentially need to make a lot of State->assume(...) calls and
see if none of the states with assumptions are null; the latter means
that you'll need to make sure you identify segments of values to avoid
calling assume() for *every* enum item. I also recommend
ConstraintManager::assumeInclusiveRange() for direct assumptions over
segments.

Your questions so far are AST questions, not specific to the analyzer.
First of all, notice that every expression has a (qualified) type, which
is the type of the value it evaluates to, and it can always be obtained
via Expr::getType(). It may be void (eg., call expression for a function
that returns void), but it's always there.

For cast-expression, as you might have already guessed, the type of the
expression is the target type of the cast. Because, well, that's the
whole point of the cast. This takes care of question 2.

Most functions return not raw Types but QualType objects that are types
with qualifiers. You can always use the overloaded operator->() on the
QualType to access the underlying Type; there's also
QualType::getTypePtr(), but if you think you need it - most likely you
don't.

Now, types, like statements or declarations, are a hierarchy. Some types
are integer types, some are array or structure types, some are enum
types. Enum types are represented by the EnumType class, to which you
can try to dyn_cast<>() your type. Or, even better, use Type::getAs<>(),
which can be accessed directly with operator->() on QualType.

If dyn_cast<>()/getAs<>() is successful - your type is an enum and you
have a pointer to an EnumType object, so you can call
EnumType::getDecl() to find the *declaration* of the enum in the code.

Also if the enum hides under a typedef, then the type wouldn't be an
EnumType but it'd be a TypedefType, so the cast would fail. The easy way
to get rid of typedefs is to do QualType::getCanonicalType().

Some declarations are forward declarations. You might need to do
EnumDecl::getDefinition() to find the actual definition. Maybe you don't
need that: i don't remember what operations are allowed on incomplete
enum types.

Once you have your EnumDecl that is the definition, you can iterate over
EnumDecl::enumerators() to see what values are present.

In Clang there are a lot more cast kinds of expressions than you
probably expect, so you might want to take a look at the list of casts
in clang/AST/OperationKinds.def and see which ones do you need; i don't
think it'll be important at first, but just in case.

In order to quickly catch up on the basics, i also recommend the AST
tutorial by Manuel Klimek at https://www.youtube.com/watch?v=VqCkCDFLSsc


On 10/24/18 5:16 PM, Alexander Zaitsev via cfe-dev wrote:
>
> Hello. I am newbie in Clang Static Analyzer and I am trying to write
> new Clang Static Analyzer check, which is aimed to find issues with
> casting values to enum: if we cast anything which is no presented in
> target enum it will be unspecified/undefined behavior(depends on C++
> version).
>
> So my plan is:
>
>  1. Find all casts in source code. Seems like
>     'check::PreStmt<CastExpr>>' it's what I need.
>  2. In my implementation of `checkPreStmt` method I must get target
>     type from CastExpr, but I don't know, how to do it - can you help
>     with it?
>  3. Then if target type in Cast is Enum, I must get all values from
>     this Enum and compare it with all possible values which can be
>     presented by CastExpr->getSubExpr() - here I don't know how to
>     evaluate CastExpr->getSubExpr() and how to get all values from Enum.
>
> Do you have any ideas?
>
> --
> Best regards,
> Alexander Zaitsev
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-- 
Best regards,
Alexander Zaitsev


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev