cgototrustzone

Strange behavior using goto for error handling in C


I am developing a basic application in C, using the OP-TEE (TrustZone Secure OS) libraries. I am running the code in QEMU. Here is the code in which the strange behavior occurred:

void prepare_rsa_operation(TEE_OperationHandle *handle, uint32_t alg, TEE_OperationMode mode, TEE_ObjectHandle key) {
    TEE_Result ret = TEE_SUCCESS;   
    TEE_ObjectInfo key_info;

    ret = TEE_GetObjectInfo1(key, &key_info);
    if (ret != TEE_SUCCESS) {
        EMSG("TEE_GetObjectInfo1: %#" PRIx32, ret);
        goto err;
    }

    ret = TEE_AllocateOperation(handle, alg, mode, key_info.keySize);
    if (ret != TEE_SUCCESS) {
        EMSG("Failed to alloc operation handle : 0x%x", ret);
        goto err;
    }
    DMSG("========== Operation allocated successfully. ==========");

    ret = TEE_SetOperationKey(*handle, key);
    if (ret != TEE_SUCCESS) {
        EMSG("Failed to set key : 0x%x", ret);
        goto err;
    }
    DMSG("========== Operation key already set. ==========");

err:
    TEE_FreeOperation(handle);
    return 1;
}

Problem that occurred:
Both successful messages were being printed (for operation allocated and key setting), but the err label was being reached even though: the TEE_FreeOperation(handle); should be written TEE_FreeOperation(*handle);. I fixed this and removed the return, since my function returns void. Now, the code is working fine, but, in my understanding, the err label should be reached only if one of the conditional tests (if's) fail, since the goto command is just inside them.

Am I wrong with this understanding? Can anyone explain me why the err label was being reached even though no error occurred before?


Solution

  • There's no special logic that prevents code from progressing past a label.

    By convention, goto is typically used in C for this type of error handing but it doesn't have to be that way. Labels for goto can be freely placed anywhere in a function. You could for example do this:

    void f()
    {
        int i;
    start:
        printf("i=%d\n", i);
        i++;
        if (i < 10) {
            goto start;
    }
    

    But please don't.