Skip to content
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

xBBCSD: read of unitialised value #943

Open
2 tasks done
christoph-conrads opened this issue Nov 24, 2023 · 0 comments · May be fixed by #967
Open
2 tasks done

xBBCSD: read of unitialised value #943

christoph-conrads opened this issue Nov 24, 2023 · 0 comments · May be fixed by #967

Comments

@christoph-conrads
Copy link
Contributor

christoph-conrads commented Nov 24, 2023

Description

Given the SBBCSD input in the C code below, xBBCSD reads an unitialized value in line 808:

CALL SLARTGS( B21E(I), B21E(I+1), NU, WORK(IU2CS+I-1),

The problem was detected by initializing all arrays with intent OUT with NaN. Valgrind's memcheck can diagnose the problem, too, if no initialization is performed.

As far as I can tell, the fix is as follows:

@@ -805,7 +805,7 @@
                CALL SLARTGP( B22BULGE, B22E(I-1), WORK(IU2SN+I-1),
      $                       WORK(IU2CS+I-1), R )
             ELSE IF( NU .LT. MU ) THEN
-               CALL SLARTGS( B21E(I), B21E(I+1), NU, WORK(IU2CS+I-1),
+               CALL SLARTGS( B21E(I), B21D(I+1), NU, WORK(IU2CS+I-1),
      $                       WORK(IU2SN+I-1) )
             ELSE
                CALL SLARTGS( B22D(I), B22E(I), MU, WORK(IU2CS+I-1),

In general, I do not comprehend the details of this functions but I arrived at this suggestion because it matches the code in lines 727, 792, and 871. Those lines reference B12D(I) and B12E(I-1), where B12D and B12E contain the Q diagonal and Q-1 subdiagonal entries, respectively, of a certain matrix. The index I can be as large as Q meaning that the reference I+1 would be out of bounds for B12E but not for B12D.

@briansutton Can you confirm the validity of the suggested patch?

Find below C99 code triggering the problem. It can be compiled as follows:

gcc -Wextra -Wall -std=c99 -pedantic sbbcsd-uninit-read.c -llapack

Output without fix (e.g., with Debian OpenBLAS 0.3.21 or commit b231dd5):

SBBCSD failed with info=3
theta     +nan     +nan     +nan +0.00e+00
phi     +nan     +nan +0.00e+00
V1T
           -nan            -nan            -nan            -nan
           +nan            +nan            +nan            +nan
           -nan            -nan            -nan            -nan
+0.000000000e+00 +0.000000000e+00 +0.000000000e+00 +1.000000000e+00

Output with SBBCSD fix:

theta +0.00e+00 +0.00e+00 +6.73e-05 +1.57e+00
phi +0.00e+00 +0.00e+00 +0.00e+00
V1T
+3.595401645e-01 -9.329686165e-01 +1.733144186e-02 +0.000000000e+00
+0.000000000e+00 +0.000000000e+00 +0.000000000e+00 +1.000000000e+00
-6.232285872e-03 +1.617212035e-02 +9.998497367e-01 +0.000000000e+00
+9.331088066e-01 +3.595941961e-01 +1.627663976e-11 +0.000000000e+00
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

typedef int lapack_int;

void sbbcsd_(
    const char* jobu1, const char* jobu2, const char* jobv1t,
    const char* jobv2t, const char* trans, const lapack_int* m,
    const lapack_int* p, const lapack_int* q, float* theta, float* phi,
    float* u1, const lapack_int* ldu1, float* u2, const lapack_int* ldu2,
    float* v1t, const lapack_int* ldv1t, float* v2t, const lapack_int* ldv2t,
    float* b11d, float* b11e, float* b12d, float* b12e, float* b21d,
    float* b21e, float* b22d, float* b22e, float* work, const lapack_int* lwork,
    lapack_int* info, size_t jobu1_len, size_t jobu2_len, size_t jobv1t_len,
    size_t jobv2t_len, size_t trans_len
);

#define M 8
#define P 4
#define Q 4

int main()
{
    float nan = NAN;
    char jobu1 = 'N';
    char jobu2 = 'N';
    char jobv1t = 'Y';
    char jobv2t = 'N';
    char trans = 'N';
    lapack_int m = M;
    lapack_int p = P;
    lapack_int q = Q;
    float u1[P * P] = { 0 };
    lapack_int ldu1 = P;
    float u2[(M - P) * (M - P)] = { 0 };
    lapack_int ldu2 = M - P;
    float v1t[Q * Q] = { 0 };
    lapack_int ldv1t = Q;
    lapack_int ldv2t = 1;
    float theta[Q]
        = { 1.20296335, 1.27602555E-02, 6.23163305E-06, 2.79734493E-08 };
    float phi[Q - 1] = { 1.57074344, 6.70322042E-05, 1.90471667E-07 };
    float b11d[Q];
    float b11e[Q - 1];
    float b12d[Q];
    float b12e[Q - 1];
    float b21d[Q];
    float b21e[Q - 1];
    float b22d[Q];
    float b22e[Q - 1];
    float work[8 * Q] = { nan };
    lapack_int lwork = sizeof(work) / sizeof(work[0]);
    lapack_int info = -1;

    //
    // Disable this for loop and the next one if you want Valgrind's memcheck
    // to detect the problem.
    //
    for(size_t i = 0; i < Q; ++i) {
        b11d[i] = nan;
        b12d[i] = nan;
        b21d[i] = nan;
        b22d[i] = nan;
    }
    for(size_t i = 0; i + 1 < Q; ++i) {
        b11e[i] = nan;
        b12e[i] = nan;
        b21e[i] = nan;
        b22e[i] = nan;
    }

    for(size_t i = 0; i < Q; ++i) {
        size_t index = i * ldv1t + i;
        v1t[index] = 1;
    }

    sbbcsd_(
        &jobu1, &jobu2, &jobv1t, &jobv2t, &trans, &m, &p, &q, theta, phi, u1,
        &ldu1, u2, &ldu2, v1t, &ldv1t, NULL, &ldv2t, b11d, b11e, b12d, b12e,
        b21d, b21e, b22d, b22e, work, &lwork, &info, 1, 1, 1, 1, 1
    );

    int exit_status = EXIT_SUCCESS;

    if(info != 0) {
        fprintf(stderr, "SBBCSD failed with info=%d\n", info);
        exit_status = EXIT_FAILURE;
    }

    printf("theta ");
    for(size_t i = 0; i < Q; ++i) {
        const char* sep = (i + 1 < Q) ? " " : "\n";
        printf("%+8.2e%s", theta[i], sep);
    }
    printf("phi ");
    for(size_t i = 0; i + 1 < Q; ++i) {
        const char* sep = (i + 2 < Q) ? " " : "\n";
        printf("%+8.2e%s", phi[i], sep);
    }


    printf("V1T\n");
    for(size_t i = 0; i < Q; ++i) {
        for(size_t j = 0; j < Q; ++j) {
            size_t index = j * ldv1t + i;
            const char* sep = (j + 1 < Q) ? " " : "\n";
            printf("%+15.9e%s", v1t[index], sep);
        }
    }

    return exit_status;
}

Checklist

  • I've included a minimal example to reproduce the issue
  • I'd be willing to make a PR to solve this issue
christoph-conrads added a commit to christoph-conrads/lapack that referenced this issue Dec 29, 2023
@christoph-conrads christoph-conrads linked a pull request Dec 29, 2023 that will close this issue
2 tasks
christoph-conrads added a commit to christoph-conrads/lapack that referenced this issue Dec 29, 2023
christoph-conrads added a commit to christoph-conrads/lapack that referenced this issue Jan 17, 2024
christoph-conrads added a commit to christoph-conrads/lapack that referenced this issue Jan 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant