DEV Community

Discussion on: I'm an Expert in Memory Management & Segfaults, Ask Me Anything!

 
lindenouwen profile image
Lindenouwen
==6225== Memcheck, a memory error detector
==6225== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6225== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==6225== Command: ./signatures
==6225== 
I succeeded in generating a key pair.
I get here
==6225== Invalid write of size 8
==6225==    at 0x109D39: PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_signature (sign.c:179)
==6225==    by 0x109DED: PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign (sign.c:210)
==6225==    by 0x1096D2: Signature::signMessage(unsigned char*, unsigned long*, unsigned char const*, unsigned long) (Signature.cpp:73)
==6225==    by 0x10946C: main (main.cpp:35)
==6225==  Address 0x1 is not stack'd, malloc'd or (recently) free'd
==6225== 
==6225== 
==6225== Process terminating with default action of signal 11 (SIGSEGV)
==6225==  Access not within mapped region at address 0x1
==6225==    at 0x109D39: PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_signature (sign.c:179)
==6225==    by 0x109DED: PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign (sign.c:210)
==6225==    by 0x1096D2: Signature::signMessage(unsigned char*, unsigned long*, unsigned char const*, unsigned long) (Signature.cpp:73)
==6225==    by 0x10946C: main (main.cpp:35)
==6225==  If you believe this happened as a result of a stack
==6225==  overflow in your program's main thread (unlikely but
==6225==  possible), you can try to increase the size of the
==6225==  main thread stack using the --main-stacksize= flag.
==6225==  The main thread stack size used in this run was 8388608.
I got infor loop works==6225== 
==6225== HEAP SUMMARY:
==6225==     in use at exit: 28 bytes in 1 blocks
==6225==   total heap usage: 11 allocs, 10 frees, 75,396 bytes allocated
==6225== 
==6225== LEAK SUMMARY:
==6225==    definitely lost: 0 bytes in 0 blocks
==6225==    indirectly lost: 0 bytes in 0 blocks
==6225==      possibly lost: 0 bytes in 0 blocks
==6225==    still reachable: 28 bytes in 1 blocks
==6225==         suppressed: 0 bytes in 0 blocks
==6225== Rerun with --leak-check=full to see details of leaked memory
==6225== 
==6225== For lists of detected and suppressed errors, rerun with: -s
==6225== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
Enter fullscreen mode Exit fullscreen mode

Here is the valgrind error message. The problem happens inside another file than the two above this one although the problem can't be there because, as said above, this is code from an almost NIST standard in post quantum and has been reviewed in correctness. For completeness, here is the code:

#include "packing.h"
#include "params.h"
#include "poly.h"
#include "polyvec.h"
#include "sign.h"
#include "randombytes.h"
#include "symmetric.h"
#include "fips202.h"
#include <stdio.h>

#include <stdint.h>

/*************************************************
* Name:        PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_keypair
*
* Description: Generates public and private key.
*
* Arguments:   - uint8_t *pk: pointer to output public key (allocated
*                             array of PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_PUBLICKEYBYTES bytes)
*              - uint8_t *sk: pointer to output private key (allocated
*                             array of PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
    uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES];
    uint8_t tr[SEEDBYTES];
    const uint8_t *rho, *rhoprime, *key;
    polyvecl mat[K];
    polyvecl s1, s1hat;
    polyveck s2, t1, t0;
    /* Get randomness for rho, rhoprime and key */
    randombytes(seedbuf, SEEDBYTES);
    shake256(seedbuf, 2 * SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES);
    rho = seedbuf;
    rhoprime = rho + SEEDBYTES;
    key = rhoprime + CRHBYTES;

    /* Expand matrix */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvec_matrix_expand(mat, rho);

    /* Sample short vectors s1 and s2 */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_uniform_eta(&s1, rhoprime, 0);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_uniform_eta(&s2, rhoprime, L);

    /* Matrix-vector multiplication */
    s1hat = s1;
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_ntt(&s1hat);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_reduce(&t1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_invntt_tomont(&t1);

    /* Add error vector s2 */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_add(&t1, &t1, &s2);

    /* Extract t1 and write public key */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_caddq(&t1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_power2round(&t1, &t0, &t1);
    PQCLEAN_DILITHIUM5AES_CLEAN_pack_pk(pk, rho, &t1);

    /* Compute H(rho, t1) and write secret key */
    shake256(tr, SEEDBYTES, pk, PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_PUBLICKEYBYTES);
    PQCLEAN_DILITHIUM5AES_CLEAN_pack_sk(sk, rho, tr, key, &t0, &s1, &s2);

    return 0;
}

/*************************************************
* Name:        PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_signature
*
* Description: Computes signature.
*
* Arguments:   - uint8_t *sig:   pointer to output signature (of length PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES)
*              - size_t *siglen: pointer to output length of signature
*              - uint8_t *m:     pointer to message to be signed
*              - size_t mlen:    length of message
*              - uint8_t *sk:    pointer to bit-packed secret key
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_signature(uint8_t *sig,
        size_t *siglen,
        const uint8_t *m,
        size_t mlen,
        const uint8_t *sk) {
    unsigned int n;
    uint8_t seedbuf[3 * SEEDBYTES + 2 * CRHBYTES];
    uint8_t *rho, *tr, *key, *mu, *rhoprime;
    uint16_t nonce = 0;
    polyvecl mat[K], s1, y, z;
    polyveck t0, s2, w1, w0, h;
    poly cp;
    shake256incctx state;

    rho = seedbuf;
    tr = rho + SEEDBYTES;
    key = tr + SEEDBYTES;
    mu = key + SEEDBYTES;
    rhoprime = mu + CRHBYTES;
    PQCLEAN_DILITHIUM5AES_CLEAN_unpack_sk(rho, tr, key, &t0, &s1, &s2, sk);

     /* Compute CRH(tr, msg) */
    shake256_inc_init(&state);
    shake256_inc_absorb(&state, tr, SEEDBYTES);
    shake256_inc_absorb(&state, m, mlen);
    shake256_inc_finalize(&state);
    shake256_inc_squeeze(mu, CRHBYTES, &state);
    shake256_inc_ctx_release(&state);

    shake256(rhoprime, CRHBYTES, key, SEEDBYTES + CRHBYTES);

    /* Expand matrix and transform vectors */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvec_matrix_expand(mat, rho);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_ntt(&s1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_ntt(&s2);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_ntt(&t0);

rej:
    /* Sample intermediate vector y */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_uniform_gamma1(&y, rhoprime, nonce++);

    /* Matrix-vector multiplication */
    z = y;
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_ntt(&z);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_reduce(&w1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_invntt_tomont(&w1);

    /* Decompose w and call the random oracle */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_caddq(&w1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_decompose(&w1, &w0, &w1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_pack_w1(sig, &w1);

    shake256_inc_init(&state);
    shake256_inc_absorb(&state, mu, CRHBYTES);
    shake256_inc_absorb(&state, sig, K * POLYW1_PACKEDBYTES);
    shake256_inc_finalize(&state);
    shake256_inc_squeeze(sig, SEEDBYTES, &state);
    shake256_inc_ctx_release(&state);
    PQCLEAN_DILITHIUM5AES_CLEAN_poly_challenge(&cp, sig);
    PQCLEAN_DILITHIUM5AES_CLEAN_poly_ntt(&cp);

    /* Compute z, reject if it reveals secret */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_pointwise_poly_montgomery(&z, &cp, &s1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_invntt_tomont(&z);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_add(&z, &z, &y);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_reduce(&z);
    if (PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
        goto rej;
    }

    /* Check that subtracting cs2 does not change high bits of w and low bits
     * do not reveal secret information */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_pointwise_poly_montgomery(&h, &cp, &s2);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_invntt_tomont(&h);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_sub(&w0, &w0, &h);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_reduce(&w0);
    if (PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_chknorm(&w0, GAMMA2 - BETA)) {
        goto rej;
    }

    /* Compute hints for w1 */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_pointwise_poly_montgomery(&h, &cp, &t0);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_invntt_tomont(&h);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_reduce(&h);
    if (PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_chknorm(&h, GAMMA2)) {
        goto rej;
    }

    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_add(&w0, &w0, &h);
    n = PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_make_hint(&h, &w0, &w1);
    if (n > OMEGA) {
        goto rej;
    }

    /* Write signature */
    PQCLEAN_DILITHIUM5AES_CLEAN_pack_sig(sig, sig, &z, &h);
    //this line is the one that gives the segmentation fault. fault is something with an invalid write somehow.
   *siglen = PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES;
    return 0;
}

/*************************************************
* Name:        PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign
*
* Description: Compute signed message.
*
* Arguments:   - uint8_t *sm: pointer to output signed message (allocated
*                             array with PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES + mlen bytes),
*                             can be equal to m
*              - size_t *smlen: pointer to output length of signed
*                               message
*              - const uint8_t *m: pointer to message to be signed
*              - size_t mlen: length of message
*              - const uint8_t *sk: pointer to bit-packed secret key
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign(uint8_t *sm,
        size_t *smlen,
        const uint8_t *m,
        size_t mlen,
        const uint8_t *sk) {
    size_t i;
    printf("I got in");
    for (i = 0; i < mlen; ++i) {
        sm[PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i];
    }
    printf("for loop works");
    PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_signature(sm, smlen, sm + PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES, mlen, sk);

    *smlen += mlen;
    return 0;
}

/*************************************************
* Name:        PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_verify
*
* Description: Verifies signature.
*
* Arguments:   - uint8_t *m: pointer to input signature
*              - size_t siglen: length of signature
*              - const uint8_t *m: pointer to message
*              - size_t mlen: length of message
*              - const uint8_t *pk: pointer to bit-packed public key
*
* Returns 0 if signature could be verified correctly and -1 otherwise
**************************************************/
int PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_verify(const uint8_t *sig,
        size_t siglen,
        const uint8_t *m,
        size_t mlen,
        const uint8_t *pk) {
    unsigned int i;
    uint8_t buf[K * POLYW1_PACKEDBYTES];
    uint8_t rho[SEEDBYTES];
    uint8_t mu[CRHBYTES];
    uint8_t c[SEEDBYTES];
    uint8_t c2[SEEDBYTES];
    poly cp;
    polyvecl mat[K], z;
    polyveck t1, w1, h;
    shake256incctx state;

    if (siglen != PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES) {
        return -1;
    }

    PQCLEAN_DILITHIUM5AES_CLEAN_unpack_pk(rho, &t1, pk);
    if (PQCLEAN_DILITHIUM5AES_CLEAN_unpack_sig(c, &z, &h, sig)) {
        return -1;
    }
    if (PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
        return -1;
    }

    /* Compute CRH(H(rho, t1), msg) */
    shake256(mu, SEEDBYTES, pk, PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_PUBLICKEYBYTES);
    shake256_inc_init(&state);
    shake256_inc_absorb(&state, mu, SEEDBYTES);
    shake256_inc_absorb(&state, m, mlen);
    shake256_inc_finalize(&state);
    shake256_inc_squeeze(mu, CRHBYTES, &state);
    shake256_inc_ctx_release(&state);

    /* Matrix-vector multiplication; compute Az - c2^dt1 */
    PQCLEAN_DILITHIUM5AES_CLEAN_poly_challenge(&cp, c);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvec_matrix_expand(mat, rho);

    PQCLEAN_DILITHIUM5AES_CLEAN_polyvecl_ntt(&z);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyvec_matrix_pointwise_montgomery(&w1, mat, &z);

    PQCLEAN_DILITHIUM5AES_CLEAN_poly_ntt(&cp);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_shiftl(&t1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_ntt(&t1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_pointwise_poly_montgomery(&t1, &cp, &t1);

    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_sub(&w1, &w1, &t1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_reduce(&w1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_invntt_tomont(&w1);

    /* Reconstruct w1 */
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_caddq(&w1);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_use_hint(&w1, &w1, &h);
    PQCLEAN_DILITHIUM5AES_CLEAN_polyveck_pack_w1(buf, &w1);

    /* Call random oracle and verify PQCLEAN_DILITHIUM5AES_CLEAN_challenge */
    shake256_inc_init(&state);
    shake256_inc_absorb(&state, mu, CRHBYTES);
    shake256_inc_absorb(&state, buf, K * POLYW1_PACKEDBYTES);
    shake256_inc_finalize(&state);
    shake256_inc_squeeze(c2, SEEDBYTES, &state);
    shake256_inc_ctx_release(&state);
    for (i = 0; i < SEEDBYTES; ++i) {
        if (c[i] != c2[i]) {
            return -1;
        }
    }

    return 0;
}

/*************************************************
* Name:        PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_open
*
* Description: Verify signed message.
*
* Arguments:   - uint8_t *m: pointer to output message (allocated
*                            array with smlen bytes), can be equal to sm
*              - size_t *mlen: pointer to output length of message
*              - const uint8_t *sm: pointer to signed message
*              - size_t smlen: length of signed message
*              - const uint8_t *pk: pointer to bit-packed public key
*
* Returns 0 if signed message could be verified correctly and -1 otherwise
**************************************************/
int PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_open(uint8_t *m,
        size_t *mlen,
        const uint8_t *sm,
        size_t smlen,
        const uint8_t *pk) {
    size_t i;

    if (smlen < PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES) {
        goto badsig;
    }

    *mlen = smlen - PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES;
    if (PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_verify(sm, PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES, sm + PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES, *mlen, pk)) {
        goto badsig;
    } else {
        /* All good, copy msg, return 0 */
        for (i = 0; i < *mlen; ++i) {
            m[i] = sm[PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES + i];
        }
        return 0;
    }

badsig:
    /* Signature verification failed */
    *mlen = (size_t) -1;
    for (i = 0; i < smlen; ++i) {
        m[i] = 0;
    }

    return -1;
}
Enter fullscreen mode Exit fullscreen mode

Thank you btw for helping me!

Thread Thread
 
codemouse92 profile image
Jason C. McDonald • Edited

The problem isn't always at the end of the stack trace, especially where memory management is involved. I don't think the library is at fault.

Actually, I think the problem is somewhere in Signature.cpp. Can you post the function in that file that includes line 73?

==6225==    by 0x1096D2: Signature::signMessage(unsigned char*, unsigned long*, unsigned char const*, unsigned long) (Signature.cpp:73)
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
lindenouwen profile image
Lindenouwen

Okay, The Signature.cpp function in which this happens is a rather short one:

#include "Signature.hpp"
#include <cstdint>
#include <iostream>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstddef>
#include <cryptopp/sha3.h>
#include <cryptopp/cryptlib.h>
#include <cryptopp/hex.h>
#include <cryptopp/filters.h>
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/files.h>

using namespace CryptoPP;

extern "C"{
     #include "api.h"
    }
using namespace std;
/*************************************************
* Name:        signMessage
*
* Description: Computes the signed message
*
* Arguments:   - uint8_t *sm: pointer to output signed
*                             message, can be equal to m
*              - size_t *smlen: pointer to output length
*                               of signed message
*              - const uint8_t *m: pointer to message to be signed
*              - size_t mlen: length of message
*
* Extra information: -*sk: pointer to secret key
*
* No Return value
**************************************************/
void Signature::signMessage(uint8_t* signedMessage, std::size_t* smLength, const uint8_t* message, std::size_t mLength){
    // if (checkPasswd(passwd)==true){
        const uint8_t *sk = getSecretKeyAddress();
        cout << "I get here" << endl;
        PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign(signedMessage, smLength, message, mLength, sk);
        cout << "not here" << endl;
    // }
}
Enter fullscreen mode Exit fullscreen mode

PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign is the c function from the library
So I think the problem might be even further back, in main.cpp, but I cannot figure out what I am doing wrong.
The main.cpp is written as follows:

#include "Signature.hpp"
#include "Signature.cpp"
#include <cstdint>
#include <iostream>
#include <cstddef>
#include <cstring>
using namespace std;
extern "C"{
     #include "api.h"
    }
int main(){
    char publicKey[PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_PUBLICKEYBYTES];
    char secretKey[PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_SECRETKEYBYTES];
    uint8_t* pk;
    pk = (uint8_t *) &publicKey;
    uint8_t* sk;
    sk = (uint8_t *) &secretKey;
    // string passwd = "admin";
    Signature sig(pk, sk);
    sig.generateKeyPair();
    cout << "I succeeded in generating a key pair." << endl;
    string mes = "I am checking if this works";
    size_t mlen = mes.length();
    char message[mlen+1];
    strcpy(message, mes.c_str());
    uint8_t* m;
    m = (uint8_t*) &message;
    mlen = sizeof(*m);
    char signedMessage[PQCLEAN_DILITHIUM5AES_CLEAN_CRYPTO_BYTES+mlen];
    uint8_t* sm;
    sm = (uint8_t*) &signedMessage;
    size_t smLength = sizeof(*sm);
    size_t* smlen;
    smlen = (size_t*) smLength;
    sig.signMessage(sm, smlen, m, mlen);
    cout << "I succeeded in signing a message." << endl;
    cout << *sm << endl;
    return 0;
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
codemouse92 profile image
Jason C. McDonald • Edited

I think I found it. The problem is in main.cpp:

    size_t smLength = sizeof(*sm);
    size_t* smlen;
    smlen = (size_t*) smLength;
    sig.signMessage(sm, smlen, m, mlen);
Enter fullscreen mode Exit fullscreen mode

There are two problems here.

  1. sizeof(*sm) gives you the length of the value pointed to by sm. This will not give you the length of the string, but rather the size of the first item in the string/array, being a character. In other words, the value here is 1, regardless of how long the string starting at pointer sm actually is. I'll come back to this.

  2. Even if smLength were correct, (size_t*) smLength; is not going to give you the address to smLength for storing in the pointer. Instead, this is casting, or reinterpreting, the value, the integer 1 in this case, as a pointer. But what's at pointer 0x00000001? Who knows. This is known as a wild pointer.

If you look throughout your code, you'll see these same mistakes occur other times, such as with mlen.

Don't take this as a criticism, but I'm dubious about where you learned to use pointers. This is pretty much a royal hash. If you learned this from an online tutorial, example, or article, I'd strongly recommend avoiding it in the future. (Check to make sure you didn't just misunderstand first.)

The reason for the segfault is that wild pointer in #2. It's looking in the wrong place for a value, and it isn't finding it. You're lucky it failed with a segfault; it could have read in literally anything that was stored at that address in memory, whether it was coincidentally correct, subtly wrong, or absolutely bonkers. These sorts of bugs are really unpredictable like that.

Here's the operations you're misunderstanding in this code:

Getting a Pointer

To get the address of a value, for storing in a pointer, use the & operator:

size_t myValue = 42;
size_t* ptrToMyValue = &myValue;
Enter fullscreen mode Exit fullscreen mode

Getting the length of a c-string (char array)

#include <string.h>

// All three of these are valid ways to declare a c-string
char* stringA = "Hi";
char stringB[] = "there";
char stringC[20] = "Lindenouwen";

size_t lengthA = strlen(stringA);  // 2
size_t lengthB = strlen(stringB);  // 5
size_t lengthC = strlen(stringC); // 11 (NOT 20!)
Enter fullscreen mode Exit fullscreen mode

By the way...

One more pro-tip: stop using the using namespace std; trick. It's an antipattern; in production code, it's all too easy to lose track of what-comes-from-where. Namespaces exist to reduce that confusion, but using namespace negates that namespace. Most examples use it for brevity; good production code never does.

Instead, explicitly spell out namespace each time:

#include <iostream>
#include <string>

std::string greeting = "Hello, world!";
std::cout << greeting << std::endl;
Enter fullscreen mode Exit fullscreen mode

Save yourself weeks of headaches and refactoring now. Never use using namespace again.

Thread Thread
 
lindenouwen profile image
Lindenouwen

Thanks for your help!
I think it works now :p

Thread Thread
 
codemouse92 profile image
Jason C. McDonald

Excellent!

You will want to get into the habit of always testing your code thoroughly in Valgrind and addressing everything it complains about; even memory leaks. Undefined behavior has a habit of hiding until the most inconvient and unexpected moment. Write tests for your code (you should be doing that anyway!), and then execute those tests both outside of and within Valgrind.