petergtz / pegomock

Pegomock is a powerful, yet simple mocking framework for the Go programming language
Apache License 2.0
252 stars 28 forks source link

code scanning alert in generated code #125

Closed dhivyasa closed 3 weeks ago

dhivyasa commented 7 months ago

The generated mock code trigged off by one error in a code scanning utility, codeQL

https://github.com/github/codeql/blob/78fcbd07d654881d9d3395efc0ea371c392529de/go/ql/src/InconsistentCode/LengthComparisonOffByOn

    params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
    if len(params) > 0 {

The check for len of params triggered it. Not sure if it is a false positive or there is abetter way to do this other than using indexes. This happened on Tracer package. Also I think all generated code follow similar pattern pegomock generate"go.opentelemetry.io/otel/trace" Tracer

petergtz commented 7 months ago

Hi @dhivyasa, thanks for reporting this. I'll have a closer look at this tomorrow. I'm almost sure this is a false positive. I don't even quite get what the scanner tries to flag 🙂. Again, I'll have a closer look tomorrow.

petergtz commented 7 months ago

@dhivyasa I had a closer look at this, specifically trying to figure out what codeQL is doing here. I must admit, it's not clear why it would flag this as an off-by-one. The examples do not relate to the actual code you pasted here and the code is also correct in what it's doing. Maybe CodeQL gets somehow confused by the fact that this is generated code and for that reason there are a lot of hardcoded indices.

Does this answer your question?

petergtz commented 4 months ago

Closing due to inactivity. Please re-open, if needed.

AndrewRPorter commented 1 month ago

Hey @petergtz 👋, I am running into this as well.

Take the following generated code snippet for example:

func (c *MockService_MethodName_OngoingVerification) GetAllCapturedArguments() (_param0 []context.Context, _param1 []*models.ModelName) {
    params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
    if len(params) > 0 {
Dismissed
        _param0 = make([]context.Context, len(c.methodInvocations))
        for u, param := range params[0] {
            _param0[u] = param.(context.Context)
        }
        _param1 = make([]*models.ModelName, len(c.methodInvocations))
        for u, param := range params[1] {
            _param1[u] = param.(*models.ModelName)
        }
    }
    return
}

I believe the CodeQL error is complaining since technically the > 0 check can pass if the length is 1 but then our params[1] would be an out of bounds access.

petergtz commented 1 month ago

Thanks for shedding light on this @AndrewRPorter. I understand it now. I think CodeQL is still wrong and the code is correct. Do you happen to know if we can add a suppression comment to avoid this false positive?

Alternatively, we could change the comparison to len(params) != 0 assuming this would satisfy CodeQL. The result of len can never be negative, so the logic is effectively equivalent.

Fancy submitting a PR?

AndrewRPorter commented 1 month ago

Do you happen to know if we can add a suppression comment to avoid this false positive?

I am able to suppress the alert as "used in tests" but for some larger mocks this can be an annoying processing suppressing many alerts.

I think CodeQL is still wrong and the code is correct.

Can you help me understand why you think this? I see the following cases,


I'm happy to help contribute a fix

petergtz commented 1 month ago

I am able to suppress the alert as "used in tests" but for some larger mocks this can be an annoying processing suppressing many alerts.

What I meant here, was: make a code change in Pegomock to generate code that tells CodeQL to ignore this. Python's flake8 linter (and others allows this via # noqa.

Can you help me understand why you think this?

There are only 2 cases:

https://github.com/petergtz/pegomock/blob/dcebf666fb90c11930948ce1ba01e079881e1a2e/mockgen/mockgen.go#L352-L373 That knowledge cannot be seen in the generated code and therefore CodeQL cannot know it. CodeQL here is really not useful.

AndrewRPorter commented 1 month ago

Thanks for explaining! Unfortunately it looks like CodeQL does not support inline suppressions right now: https://github.com/github/codeql/issues/11427.

petergtz commented 3 weeks ago

Addressed by #126. Closing this issue.