[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: fossil build failure on riscv64



Okay, the problem was this code, when called with iVal being the most
negative int:

int Th_SetResultInt(Th_Interp *interp, int iVal){
  int isNegative = 0;
  unsigned int uVal = iVal;
  char zBuf[32];
  char *z = &zBuf[32];

  if( iVal<0 ){
    isNegative = 1;
    uVal = iVal * -1;
  }
  *(--z) = '\0';
  *(--z) = (char)(48+(uVal%10));
  while( (uVal = (uVal/10))>0 ){
    *(--z) = (char)(48+(uVal%10));
    assert(z>zBuf);
  }
  if( isNegative ){
    *(--z) = '-';
  }

  return Th_SetResult(interp, z, -1);
}

The expression (char)(48+(uVal%10)), which is intended to be a digit
character '0' to '9', was coming out to values *below* 48, which are
ASCII periods and parens and such. Since uVal is unsigned, it seems
like this should not happen. So it's a compiler bug. (I think! Because
maybe the "uVal = iVal * -1" is 'undefined' when iVal is the most
negative 32-bit int, since then "iVal * -1" is not representable as a
signed int, and this licenses the compiler to shoot flaming monkeys
out its nose.)

In any case, I hope that's enough of a handle to track down what's going on.

I've fixed it with the more succinct code below, although upstream has
a ... different fix.

int Th_SetResultInt(Th_Interp *interp, int iVal){
  char zBuf[32];
  snprintf(zBuf, sizeof(zBuf), "%d", iVal);
  return Th_SetResult(interp, zBuf, -1);
}


Reply to: