Skip to content

C: refactor code to solve false positive #8739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed

Conversation

4B5F5F4B
Copy link
Contributor

I modified this query a lot to solve false positive in query https://lgtm.com/query/878361108346378150/. In this version I used global taint tracking instead of previous local taint tracking. And I changed the type of problem to path-problem to make the resutls more readable.

I modified this query a lot to solve false positive in query https://lgtm.com/query/878361108346378150/. In this version I used global taint tracking instead of previous local taint tracking
@4B5F5F4B 4B5F5F4B requested a review from a team as a code owner April 14, 2022 12:03
@github-actions github-actions bot added the C++ label Apr 14, 2022
@owen-mc owen-mc changed the title refactor code to solve false positive C: refactor code to solve false positive Apr 14, 2022
@rdmarsh2
Copy link
Contributor

Thanks for improving this query. Have you considered using the BarrierGuard and Configuration::isBarrierGuard mechanism rather than a second dataflow configuration? I think that would make this a little cleaner.

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your work on this query!

Some suggestions and questions below.

I would recommend you think about adding tests for this query in the cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020 directory. Though tests are not strictly required for queries in experimental, I think as you're doing a lot of work on this query they might have quite a lot of value.

this.getName().regexpMatch("C_SYSC_[a-zA-Z]+") or
this.getName().regexpMatch("SYSC_[a-zA-Z]+") or
this.getName().regexpMatch("compat_SyS_[a-zA-Z]+") or
this.getName().regexpMatch("SyS_[a-zA-Z]+")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for using the [a-zA-Z]+ pattern rather than .* (or .match("C_SYSC_%"))? I'm not saying one or other approach is better, just curious about the intended behaviour e.g. for functions potentially with numeric digits in their names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for using the [a-zA-Z]+ pattern rather than .* (or .match("C_SYSC_%"))? I'm not saying one or other approach is better, just curious about the intended behaviour e.g. for functions potentially with numeric digits in their names.

Hello @geoffw0 ,

As I commented in the query SysCallFunction is used to model linux syscall, and as far as I know there is no linux syscall have numeric digits in their names. And frankly speaking I don't think have numeric digits in function names is a good coding style hahah:)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per https://filippo.io/linux-syscall-table/ there seem to be some syscalls with digits such as pread64, dup2, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per https://filippo.io/linux-syscall-table/ there seem to be some syscalls with digits such as pread64, dup2, etc.

Sorry for missing your reply, Thank you. I will try out another way to model linux syscall :)

* parameter dummy will be regared as user-mode pointer used
* in unsafe_put_user without security check using access_ok
* but in fact dummy is only used to read memory otherwise
* instead of wring user-mode memory.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* instead of wring user-mode memory.
* instead of writing user-mode memory.

}

/*
* Since there is no convenient way to indentify user mode pointer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Since there is no convenient way to indentify user mode pointer,
* Since there is no convenient way to identify user mode pointer,

class UserModePtrNode extends DataFlow::Node {
UserModePtrNode() {
exists(SysCallParameter p | this.asParameter() = p) or
exists(FunctionCall va | this.asExpr() = va)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this line match only a call to a SysCallFunction?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this line match only a call to a SysCallFunction?

In this query I model taint souce comes from Linux syscall and other function return values that maybe used as user-mode pointer. So this line SysCallParameter used to model parameter from linux syscall parameter, and FunctionCall used to model other function return values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still matching every function call in the program.

Suggested change
exists(FunctionCall va | this.asExpr() = va)
exists(FunctionCall va | this.asExpr() = va and va.getTarget() instanceof SysCallFunction)

* Track all UserModePtrNode that flow to UnSafePutUserMacro
*/

class UnsafePutUserConfig extends TaintTracking::Configuration {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider overriding the isSanitizer method of this TaintTracking::Configuration to block flow through a UserModePtrCheckMacro, instead of having a separate configuration to detect when one is reachable.

Note that the meaning would not be exactly the same. A barrier has to be on the path in question, whereas your UserModePtrCheckConfig taint tracking configuration looks for any reachable UserModePtrCheckMacro (even if, for example, it comes after the unsafe put).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, @geoffw0

You are absolutely right isSanitizer or isBarrier is the most way to whether user-mode pointer node flow through a UserModePtrCheckMacro, but it doest not work and I don't know why.

I have tried to define UnsafePutUserConfig in this way

class UnsafePutUserConfig extends TaintTracking::Configuration {
  UnsafePutUserConfig() { this = "UnsafePutUserConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UnSafePutUserMacro m | node.asExpr() = m.getExprOperand())
  }

  override predicate isSanitizer(DataFlow::Node node){
    exists(UserModePtrCheckMacro m | 
        node.asExpr() = m.getArgument()
    )
  }
}

or like this

class UnsafePutUserConfig extends DataTracking::Configuration {
  UnsafePutUserConfig() { this = "UnsafePutUserConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UnSafePutUserMacro m | node.asExpr() = m.getExprOperand())
  }

  override predicate isBarrier(DataFlow::Node node){
    exists(UserModePtrCheckMacro m | 
        node.asExpr() = m.getArgument()
    )
  }
}

But isSanitizer or isBarrier neither blocks the data flow from source to unsafe_put_user, can cause many false positives. for example, the following code is not buggy, but my query will think ptr is not validated before use

void function foo()
{
       void* ptr = func_return_user_mode_pointer();
       bar(ptr);    
}

void function bar(void * ptr)
{
      if(!access_ok(ptr))
           return;
      usafe_put_user(0x41414141, ptr)  
}

This is why I defined another taint config UserModePtrCheckConfig:(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, @geoffw0

You are absolutely right isSanitizer or isBarrier is the most way to whether user-mode pointer node flow through a UserModePtrCheckMacro, but it doest not work and I don't know why.

I have tried to define UnsafePutUserConfig in this way

class UnsafePutUserConfig extends TaintTracking::Configuration {
  UnsafePutUserConfig() { this = "UnsafePutUserConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UnSafePutUserMacro m | node.asExpr() = m.getExprOperand())
  }

  override predicate isSanitizer(DataFlow::Node node){
    exists(UserModePtrCheckMacro m | 
        node.asExpr() = m.getArgument()
    )
  }
}

or like this

class UnsafePutUserConfig extends DataTracking::Configuration {
  UnsafePutUserConfig() { this = "UnsafePutUserConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UnSafePutUserMacro m | node.asExpr() = m.getExprOperand())
  }

  override predicate isBarrier(DataFlow::Node node){
    exists(UserModePtrCheckMacro m | 
        node.asExpr() = m.getArgument()
    )
  }
}

But isSanitizer or isBarrier neither blocks the data flow from source to unsafe_put_user, can cause many false positives. for example, the following code is not buggy, but my query will think ptr is not validated before use

void function foo()
{
       void* ptr = func_return_user_mode_pointer();
       bar(ptr);    
}

void function bar(void * ptr)
{
      if(!access_ok(ptr))
           return;
      usafe_put_user(0x41414141, ptr)  
}

This is why I defined another taint config UserModePtrCheckConfig:(

@rdmarsh2 Thanks for your advice, Would you mind to take a look at my comments above? isSanitizer or isBarrier does not work for me, but I will try Configuration::isBarrierGuard

@4B5F5F4B
Copy link
Contributor Author

Thanks for improving this query. Have you considered using the BarrierGuard and Configuration::isBarrierGuard mechanism rather than a second dataflow configuration? I think that would make this a little cleaner.

Hello @rdmarsh2

Really confused, I even think I may ran into some bugs in CodeQL:(, I defiend DataFlow::BarrierGuard like this

class UserModePtrCheckBarrierGuard extends DataFlow::BarrierGuard{
  UserModePtrCheckMacro m;

  UserModePtrCheckBarrierGuard(){
      this.getAChild() = m.getArgument()   
  }

  override predicate checks(Expr checked, boolean isTrue){
    checked = m.getArgument()  and
    isTrue = false 
  }
}

and override isSanitizerGuard in taint tracking configuration


  override predicate isSanitizerGuard(DataFlow::BarrierGuard bg){
     bg instanceof UserModePtrCheckBarrierGuard
  }

But there are still many obvious false positives you can see the pic I attached

screenshot-20220415-152907

@4B5F5F4B
Copy link
Contributor Author

Thanks for improving this query. Have you considered using the BarrierGuard and Configuration::isBarrierGuard mechanism rather than a second dataflow configuration? I think that would make this a little cleaner.

Hello @rdmarsh2 @geoffw0

I'm really confused, you can see in my attached pic data flow does not go through user_access_begin

screenshot-20220415-190649

But the predicate checked holds for user_access_begin

screenshot-20220415-190941

@4B5F5F4B
Copy link
Contributor Author

If I defined a taint tracking config without any sanitizer or barrier, I found that data flow does not flow through any UserModePtrCheckMacro node defined in a If statement

/*
 *  Track all UserModePtrNode that flow to UnSafePutUserMacro
 */

class UnsafePutUserConfig extends TaintTracking::Configuration {
  UnsafePutUserConfig() { this = "UnsafePutUserConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UnSafePutUserMacro m | node.asExpr() = m.getExprOperand())
  }

}


from UnsafePutUserConfig config, DataFlow::PathNode sink, DataFlow::PathNode src
where
  config.hasFlowPath(src, sink) 
select sink, src, sink, "write user-mode pointer $@ without validation.", src, src.toString()

for following code

frame = get_sigframe(ksig, regs, sizeof(*frame), &fp);  

if (!user_access_begin(frame, sizeof(*frame)))          //this  is ignored on taint flow  path
	return -EFAULT;

unsafe_put_user(sig, &frame->sig, Efault);                   

the taint flow path query result is

Path:

  1. call to get_sigframe
  2. frame used in unsafe_put_user

user_access_begin expaned in if statement is ignored

@4B5F5F4B
Copy link
Contributor Author

Hello @rdmarsh2 @geoffw0

Is this a bug in CodeQL, I use CodeQL CLI v2.8.5 FYI

@4B5F5F4B
Copy link
Contributor Author

Really confused:(

I don't know why UserModePtrCheckConfig can track taint from UserModePtrNode to UserModePtrCheckMacro

/*
 *  Track all UsermodePtrNode that flow to UserModePtrCheckMacro
 */

class UserModePtrCheckConfig extends TaintTracking::Configuration {
  UserModePtrCheckConfig() { this = "UserModePtrCheckConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UserModePtrCheckMacro m | node.asExpr() = m.getArgument())
  }
}

from UserModePtrCheckConfig config, UserModePtrNode ptr, DataFlow::PathNode sink, DataFlow::PathNode src
where 
    config.hasFlowPath(src, sink) and
    src.getNode() = ptr
select 
    src, src, sink, "path"

screenshot-20220415-205655

@rdmarsh2
Copy link
Contributor

I'm really confused, you can see in my attached pic data flow does not go through user_access_begin

That's expected - that use isn't part of the dataflow path here, since it's consumed by user_access_begin and then discarded. The BarrierGuard mechanism is used to handle this situation. I think the only problem here is that you need isTrue = true in the checks method, since it's going to be the result of user_access_begin before any negation.

@4B5F5F4B
Copy link
Contributor Author

I'm really confused, you can see in my attached pic data flow does not go through user_access_begin

That's expected - that use isn't part of the dataflow path here, since it's consumed by user_access_begin and then discarded. The BarrierGuard mechanism is used to handle this situation. I think the only problem here is that you need isTrue = true in the checks method, since it's going to be the result of user_access_begin before any negation.

Hello @rdmarsh2

Thanks for your advice, but in fact I also tried isTrue=false before, it doest not work neither, there are still same false positives

class UserModePtrCheckBarrierGuard extends DataFlow::BarrierGuard {
  UserModePtrCheckBarrierGuard() {
    exists(UserModePtrCheckMacro m |
      this.getAChild() = m.getArgument()
    )
  }

  override predicate checks(Expr checked, boolean isTrue) {
    checked = this.getAChild() and
    isTrue = true
  }
}

/*
 *  Track all UserModePtrNode that flow to UnSafePutUserMacro
 */

class UnsafePutUserConfig extends TaintTracking::Configuration {
  UnsafePutUserConfig() { this = "UnsafePutUserConfig" }

  override predicate isSource(DataFlow::Node node) { node instanceof UserModePtrNode }

  override predicate isSink(DataFlow::Node node) {
    exists(UnSafePutUserMacro m | node.asExpr() = m.getExprOperand())
  }

  override predicate isSanitizerGuard(DataFlow::BarrierGuard bg){
    bg instanceof UserModePtrCheckBarrierGuard
 }
}

I had ran quick evaluation for isSanitizerGuard, and I can get a lot results of call to user_access_begin as my pic attached shows

@rdmarsh2 @geoffw0

screenshot-20220416-170510

@4B5F5F4B
Copy link
Contributor Author

I'm really confused, you can see in my attached pic data flow does not go through user_access_begin

That's expected - that use isn't part of the dataflow path here, since it's consumed by user_access_begin and then discarded. The BarrierGuard mechanism is used to handle this situation. I think the only problem here is that you need isTrue = true in the checks method, since it's going to be the result of user_access_begin before any negation.

Hello @rdmarsh2

As you put it user_access_begin is not part of dataflow path here, so I think predicate isSanitizerGuard is also useless here since isSanitizerGuard is intented to stop dataflow, but in fact user_access_begin is not part of dataflow

@4B5F5F4B
Copy link
Contributor Author

Thank you for your work on this query!

Some suggestions and questions below.

I would recommend you think about adding tests for this query in the cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020 directory. Though tests are not strictly required for queries in experimental, I think as you're doing a lot of work on this query they might have quite a lot of value.

Hello @geoffw0

I found that some latest version of Linux kernel have another to define syscall, and my query fails to select them. I'll try some other ways

@4B5F5F4B
Copy link
Contributor Author

Hello @geoffw0

Are you still working on this pull request? I think I can not have better way to solve problem we discussed above

@geoffw0
Copy link
Contributor

geoffw0 commented Apr 21, 2022

Hi @4B5F5F4B, please see #8800. Once we've agreed some test cases I'll take another look at what's going on here.

@4B5F5F4B
Copy link
Contributor Author

Hi @4B5F5F4B, please see #8800. Once we've agreed some test cases I'll take another look at what's going on here.

OK, I'll try to provide you some testcases

As @rdmarsh2 suggest I tried to use Configuration::isBarrierGuard to avoid twice taint tracking, but it does not work
@4B5F5F4B
Copy link
Contributor Author

4B5F5F4B commented May 6, 2022

Hi @4B5F5F4B, please see #8800. Once we've agreed some test cases I'll take another look at what's going on here.

@geoffw0 Sorry for some delay, as you add some testcases and I commit another version of my query to help you have a close look

@geoffw0
Copy link
Contributor

geoffw0 commented May 10, 2022

Hi @4B5F5F4B,

I've just had a good look at your query and I think your sources (UserModePtrNode) are broken. Just about every line of code has an Expr that's currently a source, as a result every sink is reached (from the source on the same line) regardless of where barriers and barrier guards occur.

Try replacing UserModePtrNode with something like:

class UserModePtrNode extends DataFlow::Node {
  UserModePtrNode() {
    exists(SysCallFunction f |
      f.getACallToThisFunction().getAnArgument() = this.asDefiningArgument()
    )
  }
}

.asDefiningArgument() here replaces the usual .asExpr(), because we want the value 'output' by this pointer parameter. If we leave it as .asExpr(), the sources will be the values input to the system calls, which do not necessarily flow through them. This is a bit of a subtle point.

On to those barriers. I had a bit of trouble with BarrierGuard, but a rather manual isBarrier solution works for me:

override predicate isBarrier(DataFlow::Node node) {
  exists(FunctionCall fc, Expr arg, Expr checked |
    // `fc` is a call that's part of a `UserModePtrCheckMacro`
    fc = any(UserModePtrCheckMacro m).getAnInvocation().getAnExpandedElement() and
    // `arg` is used in an argument to it
    arg = fc.getAnArgument().getAChild*() and
    // `checked` has the same value as `arg`
    checked = globalValueNumber(arg).getAnExpr() and
    // `checked` comes before `fc`
    dominates(checked, fc) and
    (
      node.asExpr() = checked or
      node.asDefiningArgument() = checked
    )
  )
}

Its not perfect yet, but I was able to get good results on the tests with these changes. Hope that helps!

@4B5F5F4B
Copy link
Contributor Author

4B5F5F4B commented May 11, 2022

Hi @4B5F5F4B,

I've just had a good look at your query and I think your sources (UserModePtrNode) are broken. Just about every line of code has an Expr that's currently a source, as a result every sink is reached (from the source on the same line) regardless of where barriers and barrier guards occur.

Try replacing UserModePtrNode with something like:

class UserModePtrNode extends DataFlow::Node {
  UserModePtrNode() {
    exists(SysCallFunction f |
      f.getACallToThisFunction().getAnArgument() = this.asDefiningArgument()
    )
  }
}

.asDefiningArgument() here replaces the usual .asExpr(), because we want the value 'output' by this pointer parameter. If we leave it as .asExpr(), the sources will be the values input to the system calls, which do not necessarily flow through them. This is a bit of a subtle point.

On to those barriers. I had a bit of trouble with BarrierGuard, but a rather manual isBarrier solution works for me:

override predicate isBarrier(DataFlow::Node node) {
  exists(FunctionCall fc, Expr arg, Expr checked |
    // `fc` is a call that's part of a `UserModePtrCheckMacro`
    fc = any(UserModePtrCheckMacro m).getAnInvocation().getAnExpandedElement() and
    // `arg` is used in an argument to it
    arg = fc.getAnArgument().getAChild*() and
    // `checked` has the same value as `arg`
    checked = globalValueNumber(arg).getAnExpr() and
    // `checked` comes before `fc`
    dominates(checked, fc) and
    (
      node.asExpr() = checked or
      node.asDefiningArgument() = checked
    )
  )
}

Its not perfect yet, but I was able to get good results on the tests with these changes. Hope that helps!

Hello @geoffw0
Thanks for your reviewing, but I think globalValueNumber is too slow to query large codebase like Linux kernel, the query is even slower than my previous version in which I used twice global taint flow configuration that produces good results as expected.

So I think there seems to no no much point in using something like isBarrier or BarrierGuard, twice global taint flow configuration is good enough.

@geoffw0
Copy link
Contributor

geoffw0 commented May 12, 2022

OK, I'll run the checks on the query as it is now then...

roll back to twice global taint tracking to ensure less false positive and effeciency
@4B5F5F4B
Copy link
Contributor Author

4B5F5F4B commented May 14, 2022

OK, I'll run the checks on the query as it is now then...

Hello @geoffw0

Thank you but I make another commit to roll back to twice global taint tracking, and choose another to model linux syscall.

@4B5F5F4B
Copy link
Contributor Author

OK, I'll run the checks on the query as it is now then...

Hello @geoffw0

Thank you but I make another commit to roll back to twice global taint tracking, and choose another to model linux syscall.

Hello @geoffw0

Would you mind to have a look at my new commit?

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with rolling this back to the two dataflow configs solution, but the definition of UserModePtrNode still doesn't look right to me.

class UserModePtrNode extends DataFlow::Node {
UserModePtrNode() {
exists(SysCallParameter p | this.asParameter() = p) or
exists(FunctionCall va | this.asExpr() = va)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still matching every function call in the program.

Suggested change
exists(FunctionCall va | this.asExpr() = va)
exists(FunctionCall va | this.asExpr() = va and va.getTarget() instanceof SysCallFunction)


class UserModePtrNode extends DataFlow::Node {
UserModePtrNode() {
exists(SysCallParameter p | this.asParameter() = p) or

Check warning

Code scanning / CodeQL

Expression can be replaced with a cast

The assignment to [p](1) in the exists(..) can replaced with an instanceof expression.
class UserModePtrNode extends DataFlow::Node {
UserModePtrNode() {
exists(SysCallParameter p | this.asParameter() = p) or
exists(FunctionCall va | this.asExpr() = va)

Check warning

Code scanning / CodeQL

Expression can be replaced with a cast

The assignment to [va](1) in the exists(..) can replaced with an instanceof expression.
4B5F5F4B and others added 3 commits May 21, 2022 18:43
…fePutUser.ql

Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
…fePutUser.ql

Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
…fePutUser.ql

Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
@4B5F5F4B
Copy link
Contributor Author

Hello @geoffw0

Thank you again for your reviewing my code, but I have to explain why I model UserModePtrNode in following code

class UserModePtrNode extends DataFlow::Node {
  UserModePtrNode() {
    exists(SysCallParameter p | this.asParameter() = p) or
    exists(FunctionCall va | this.asExpr() = va)
  }
}

As I left in comment since there is no convient way to identify user mode pointer, In this query syscall parameter or any function return value will be regared source node that's used as user mode pointer. Please consider following example

void foo()
{
unsigned int* user_mode_ptr = some_function_call_return_user_mode_pointer();
unsafe_put_user(user_mode_ptr, 0x41414141, sizeof(unsigned int)); //user_mode_ptr is used without any check
}

@geoffw0
Copy link
Contributor

geoffw0 commented May 23, 2022

OK, I understand now.

It looks like this branch needs merging with main, then I'll run the checks again.

I can't find any real world results for this query, because its really specialized for the Linux kernel so there isn't a lot of code out there to try it on. We will have to depend on the tests to reveal how well it works.

@4B5F5F4B
Copy link
Contributor Author

OK, I understand now.

It looks like this branch needs merging with main, then I'll run the checks again.

I can't find any real world results for this query, because its really specialized for the Linux kernel so there isn't a lot of code out there to try it on. We will have to depend on the tests to reveal how well it works.

OK

@4B5F5F4B
Copy link
Contributor Author

OK, I understand now.

It looks like this branch needs merging with main, then I'll run the checks again.

I can't find any real world results for this query, because its really specialized for the Linux kernel so there isn't a lot of code out there to try it on. We will have to depend on the tests to reveal how well it works.

When will the query merger into main branch?

@geoffw0
Copy link
Contributor

geoffw0 commented May 25, 2022

Ah, sorry, I thought it had merge conflicts (misreading the new interface). I've started the checks. Happy to merge if everything looks good after that.

@geoffw0
Copy link
Contributor

geoffw0 commented May 25, 2022

The test is failing with the following difference:

-| test.cpp:14:16:14:16 | p | unsafe_put_user write user-mode pointer $@ without check. | test.cpp:14:16:14:16 | p | p |

That's the only result of the test, so its saying we now get no results. This suggests to me that something is going wrong in the query (or perhaps the test isn't close enough to reality).

@4B5F5F4B 4B5F5F4B closed this May 26, 2022
@MathiasVP
Copy link
Contributor

Was this closed on purpose @4B5F5F4B?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants