-2

use a encryptedString replace a GlobalVariable but type not match.

the GlobalVariable a const char * string. code like that:

   GlobalVariable* GV = *it;
   //get clear text string
   std::string clearstr = getGlobalStringValue(GV);
   GlobalVariable::LinkageTypes lt = GV->getLinkage();
   //encrypt current string
   std::string encryptedString = stringEncryption(clearstr);    
   //create new global string with the encrypted string
   std::ostringstream oss;
   oss << ".encstr" << encryptedStringCounter << "_" << sys::Process::GetRandomNumber();
   Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, true);
   GlobalVariable* gCryptedStr = new GlobalVariable(M, cryptedStr->getType(), true, GV->getLinkage(), cryptedStr, oss.str());
   StringMapGlobalVars[oss.str()] = gCryptedStr;
   //replace use of clear string with encrypted string
   GV->replaceAllUsesWith(gCryptedStr);

but failed with:

Assertion failed: (New->getType() == getType() && "replaceAllUses of value with new value of different type!"),

Michael Haidl
  • 5,384
  • 25
  • 43
AloneMonkey
  • 111
  • 8

2 Answers2

1

At first: I recommend replacing everything with the right type in LLVM IR that's why this assertion is there.

However:

You get this assertion because your strings does not match in length. A global string is represented as an array of characters (i.e. i8 values). So the type of your string is [len x i8] where len is the length of your string.

@.str = private unnamed_addr constant [12 x i8] c"hello world\00", align 1

What you can do is write your own replacement function like this:

template<typename T>
void ReplaceUnsafe(T *from, T *to) {

  while (!from->use_empty()) {
    auto &U = *from->use_begin();
    U.set(to);
  }
  from->eraseFromParent();
}

However, this is (as the function name indicates) unsafe and here is why:

Consider the following C/C++ code:

int main() {
   return "hello world"[9];
}

which will just return the int representation of l.

Compiled to IR it looks like this:

@.str = private unnamed_addr constant [12 x i8] c"hello world\00", align 1

; Function Attrs: nounwind
define i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  store i32 0, i32* %retval
  %0 = load i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i64 9), align 1
  %conv = sext i8 %0 to i32
  ret i32 %conv
}

if the string is now replaced with somiting of unequal type (e.g., something of type [7 x i8]), then you may end up with a problem because your GEP instruction has the 9 as contant index. This will result in an out of bounds access. I don't know if the llvm verify pass catches this when it looks at GEP instructions (if you run it).

Michael Haidl
  • 5,384
  • 25
  • 43
  • if replaced with type [7 x i8] , and "getelementptr inbounds ([12 x i8]* @.str, i32 0, i64 9)" will change to "getelementptr inbounds ([7 x i8]* @.str, i32 0, i64 9)" ? – AloneMonkey Feb 12 '15 at 08:48
  • yes, if you look in the `replaceAllUsesWith` function of the Value class you will see that the `ReplaceUnsafe` function does basically the same. And there are no semantic checks behind the `replaceAllUsesWith` function. All you have is the verify pass that checks (some) mistakes that could be done in IR and I assume it will tell you something is wrong with your GEP instruction but i don't know for sure. – Michael Haidl Feb 12 '15 at 09:17
  • I find a problem:std::string str("whatup, world");str.length() is 13,but ConstantDataSequential->getAsString() is 14. – AloneMonkey Feb 13 '15 at 03:08
0
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, true);

change to

Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, false);
sinsuren
  • 1,745
  • 2
  • 23
  • 26
wang123
  • 11
  • 2