pepper-project / pequin

A system for verifying outsourced computations, and applying SNARKs. Simplified release of the main Pepper codebase.
Other
122 stars 46 forks source link

Evaluation of pointer #52

Open MorelSerge opened 5 years ago

MorelSerge commented 5 years ago

I'm stumbling on a weird error. I got an array of structs like this:

typedef struct triple_pattern {
  uint8_t subject[MAX_TP_OBJ_LENGTH];
  uint8_t predicate[MAX_TP_OBJ_LENGTH];
  uint8_t object[MAX_TP_OBJ_LENGTH];
} triple_pattern_t;
triple_pattern_t triple_patterns[MAX_TP];
uint8_t c_tp_part[MAX_TP_OBJ_LENGTH];

Now I have a separate state variable int state_a, which I then use to access triple_patterns like this:

if (state_a < MAX_TP) {
  triple_patterns[state_a].subject = c_tp_part;
}

This does not work, see stacktrace below. What does work is this:

int j;
for (j = 0; j < MAX_TP; j++) {
  if (j == state_a) {
    triple_patterns[j].subject = c_tp_part;
  }
}

What am I missing in the first example that makes it fail to compile?

Thanks

Stacktrace:

Expanding circuit to file compute.c.ZAATAR.circuit Exception in thread "main" java.lang.RuntimeException: I don't know how to evaluate the value of the pointer. at SFE.Compiler.Operators.PointerAccessOperator.evaluatePossibleValues(PointerAccessOperator.java:330) at SFE.Compiler.Operators.PointerAccessOperator.evaluatePossibleValues(PointerAccessOperator.java:305) at SFE.Compiler.Operators.PointerAccessOperator.evaluatePossibleValues(PointerAccessOperator.java:315) at SFE.Compiler.Operators.PointerAccessOperator.asAddressInternal(PointerAccessOperator.java:229) at SFE.Compiler.Operators.PointerAccessOperator.asAddressInternal(PointerAccessOperator.java:240) at SFE.Compiler.Operators.PointerAccessOperator.asAddress(PointerAccessOperator.java:141) at SFE.Compiler.ProtoAssignmentStatement.toAssignmentStatements(ProtoAssignmentStatement.java:75) at ccomp.parser_hw.CCompiler.addStatement(CCompiler.java:521) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:997) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:793) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:851) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:851) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:873) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:873) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:873) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:851) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:851) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:695) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.genericFunctionCall(CCompiler.java:1050) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:958) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:793) at ccomp.parser_hw.CCompiler.getExpr(CCompiler.java:814) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:660) at ccomp.parser_hw.CCompiler.expandStatement(CCompiler.java:635) at ccomp.parser_hw.CCompiler.access$1100(CCompiler.java:114) at ccomp.parser_hw.CCompiler$CMainStatement.toAssignmentStatements(CCompiler.java:491) at SFE.Compiler.BlockStatement.toAssignmentStatements(BlockStatement.java:111) at SFE.Compiler.FunctionBody.toAssignmentStatements(FunctionBody.java:31) at zcc.ZCC.compile(ZCC.java:260) at zcc.ZCC.main(ZCC.java:127) Makefile:113: recipe for target 'bin/compute.params' failed make: *** [bin/compute.params] Error 1

maxhowald commented 5 years ago

Thanks for the report! Do you have a minimal example that throws the error? I couldn't seem to reproduce it with just the just your snippet, using the code below (with inputs and outputs to ensure the whole computation isn't optimized to nothing...):

#include <stdint.h>

#define MAX_TP_OBJ_LENGTH 5
#define MAX_TP 5

typedef struct triple_pattern {
    uint8_t subject[MAX_TP_OBJ_LENGTH];
    uint8_t predicate[MAX_TP_OBJ_LENGTH];
    uint8_t object[MAX_TP_OBJ_LENGTH];
} triple_pattern_t;
triple_pattern_t triple_patterns[MAX_TP];
uint8_t c_tp_part[MAX_TP_OBJ_LENGTH];

struct In {
    int a;
};

struct Out {
    int b;
};

int compute(struct In *input, struct Out *output) {
    int j;
    for (j = 0; j < MAX_TP_OBJ_LENGTH; j++) {
        c_tp_part[j] = input->a;
    }

    int state_a = input->a;

    if (state_a < MAX_TP) {
        triple_patterns[state_a].subject = c_tp_part;
        output->b = triple_patterns[state_a].subject[0];
    }
}
MorelSerge commented 5 years ago

Hi, thanks for getting back to me! I reduced my code to the least amount possible that produces the same error:

Compute.c

#include <stdint.h>
#include "compute.h"

int compute(In_t *input, Out_t *output) {
  output_t objects[MAX_TP];
  extract(input->input, objects);
}

int extract(uint8_t input[MAX_INPUT], output_t objects[MAX_TP]) {
  int i, j, k;
  uint8_t c_char;
  uint8_t c_tp_part[MAX_TP_OBJ_LENGTH];

  k = 0;
  j = 0;
  for (i = 0; i < MAX_INPUT; i++) {
    c_char = input[i];
    if (c_char != UNDEFINED) {
      if (j == 0) {
        j = 1;
      } else {
        if (k == 0 && j - 1 < MAX_TP) {
          objects[j - 1].a = c_tp_part;
        }
      }
    }
  }
  return 1;
}

Compute.h

#define MAX_INPUT 500
#define MAX_RESULTS 10
#define MAX_TP_OBJ_LENGTH 10
#define MAX_TP_LENGTH  3 * MAX_TP_OBJ_LENGTH + 3
#define MAX_TP 3
#ifndef UNDEFINED
  #define UNDEFINED 0
#endif

typedef struct In {
    uint8_t input[MAX_INPUT];
} In_t;

typedef struct output {
  uint8_t a[MAX_TP_OBJ_LENGTH];
  uint8_t b[MAX_TP_OBJ_LENGTH];
  uint8_t c[MAX_TP_OBJ_LENGTH];
} output_t;

typedef struct Out {
  output_t results[MAX_RESULTS];
} Out_t;

Can you reproduce the exception with this?

maxhowald commented 5 years ago

I was able to reproduce the error you got, thanks.

It looks like this is a bug in the way that the compiler handles passing arrays of structs with array members to functions. I'll try to look into this a bit more deeply and get back to you, but as a workaround, you could try moving the declaration to a global variable.

For example, the following compiles without error:

#include <stdint.h>
#include "compute.h"

output_t objects[MAX_RESULTS];
int compute(In_t *input, Out_t *output) {
  extract(input->input);
  output->results = objects;
}

int extract(uint8_t input[MAX_INPUT]) {
  int i, j, k;
  uint8_t c_char;
  uint8_t c_tp_part[MAX_TP_OBJ_LENGTH];

  k = 0;
  j = 0;
  for (i = 0; i < MAX_INPUT; i++) {
    c_char = input[i];
    if (c_char != UNDEFINED) {
      if (j == 0) {
        j = 1;
      } else {
        if (k == 0 && j - 1 < MAX_TP) {
          objects[j - 1].a = c_tp_part;
        }
      }
    }
  }
  return 1;
}
MorelSerge commented 5 years ago

This does compile successfully! Thank you.

One thing that might help you find the bug is that even removing 1 "if" statement in the code I previously posted, makes it work.