@@ -110,40 +110,46 @@ ObjectState::ObjectState(const MemoryObject *mo, const Array *array, KType *dt)
110110 : copyOnWriteOwner(0 ), object(mo), valueOS(ObjectStage(array, nullptr )),
111111 baseOS(ObjectStage(array->size, Expr::createPointer(0 ), false,
112112 Context::get().getPointerWidth())),
113+ taintOS(ObjectStage(array->size, Expr::createEmptyTaint(), false, Expr::TaintWidth)),
113114 lastUpdate(nullptr ), size(array->size), dynamicType(dt), readOnly(false ) {
114115 baseOS.initializeToZero ();
116+ taintOS.initializeToZero ();
115117}
116118
117119ObjectState::ObjectState (const MemoryObject *mo, KType *dt)
118120 : copyOnWriteOwner(0 ), object(mo),
119121 valueOS(ObjectStage(mo->getSizeExpr (), nullptr)),
120122 baseOS(ObjectStage(mo->getSizeExpr (), Expr::createPointer(0 ), false,
121123 Context::get().getPointerWidth())),
124+ taintOS(ObjectStage(mo->getSizeExpr (), Expr::createEmptyTaint(), false, Expr::TaintWidth)),
122125 lastUpdate(nullptr ), size(mo->getSizeExpr ()), dynamicType(dt),
123126 readOnly(false ) {
124127 baseOS.initializeToZero ();
128+ taintOS.initializeToZero ();
125129}
126130
127131ObjectState::ObjectState (const ObjectState &os)
128132 : copyOnWriteOwner(0 ), object(os.object), valueOS(os.valueOS),
129- baseOS(os.baseOS), lastUpdate (os.lastUpdate ), size (os.size ),
130- dynamicType(os.dynamicType), readOnly(os.readOnly),
133+ baseOS(os.baseOS), taintOS (os.taintOS ), lastUpdate (os.lastUpdate ),
134+ size(os.size), dynamicType(os.dynamicType), readOnly(os.readOnly),
131135 wasWritten(os.wasWritten) {}
132136
133137/* **/
134138
135139void ObjectState::initializeToZero () {
136140 valueOS.initializeToZero ();
137141 baseOS.initializeToZero ();
142+ taintOS.initializeToZero ();
138143}
139144
140145ref<Expr> ObjectState::read8 (unsigned offset) const {
141146 ref<Expr> val = valueOS.readWidth (offset);
142147 ref<Expr> base = baseOS.readWidth (offset);
143- if (base->isZero ()) {
148+ ref<Expr> taint = taintOS.readWidth (offset);
149+ if (base->isZero () && taint->isZero ()) {
144150 return val;
145151 } else {
146- return PointerExpr::create (base, val);
152+ return PointerExpr::create (base, val, taint );
147153 }
148154}
149155
@@ -155,6 +161,10 @@ ref<Expr> ObjectState::readBase8(unsigned offset) const {
155161 return baseOS.readWidth (offset);
156162}
157163
164+ ref<Expr> ObjectState::readTaint8 (unsigned offset) const {
165+ return taintOS.readWidth (offset);
166+ }
167+
158168ref<Expr> ObjectState::read8 (ref<Expr> offset) const {
159169 assert (!isa<ConstantExpr>(offset) &&
160170 " constant offset passed to symbolic read8" );
@@ -177,10 +187,11 @@ ref<Expr> ObjectState::read8(ref<Expr> offset) const {
177187 }
178188 ref<Expr> val = valueOS.readWidth (offset);
179189 ref<Expr> base = baseOS.readWidth (offset);
180- if (base->isZero ()) {
190+ ref<Expr> taint = taintOS.readWidth (offset);
191+ if (base->isZero () && taint->isZero ()) {
181192 return val;
182193 } else {
183- return PointerExpr::create (base, val);
194+ return PointerExpr::create (base, val, taint );
184195 }
185196}
186197
@@ -230,21 +241,48 @@ ref<Expr> ObjectState::readBase8(ref<Expr> offset) const {
230241 return baseOS.readWidth (offset);
231242}
232243
244+ ref<Expr> ObjectState::readTaint8 (ref<Expr> offset) const {
245+ assert (!isa<ConstantExpr>(offset) &&
246+ " constant offset passed to symbolic read8" );
247+
248+ if (object) {
249+ if (ref<ConstantExpr> sizeExpr =
250+ dyn_cast<ConstantExpr>(object->getSizeExpr ())) {
251+ auto moSize = sizeExpr->getZExtValue ();
252+ if (object && moSize > 4096 ) {
253+ std::string allocInfo;
254+ object->getAllocInfo (allocInfo);
255+ klee_warning_once (nullptr ,
256+ " Symbolic memory access will send the following "
257+ " array of %lu bytes to "
258+ " the constraint solver -- large symbolic arrays may "
259+ " cause significant "
260+ " performance issues: %s" ,
261+ moSize, allocInfo.c_str ());
262+ }
263+ }
264+ }
265+ return taintOS.readWidth (offset);
266+ }
267+
233268void ObjectState::write8 (unsigned offset, uint8_t value) {
234269 valueOS.writeWidth (offset, value);
235270 baseOS.writeWidth (offset,
236271 ConstantExpr::create (0 , Context::get ().getPointerWidth ()));
272+ taintOS.writeWidth (offset, Expr::createEmptyTaint ());
237273}
238274
239275void ObjectState::write8 (unsigned offset, ref<Expr> value) {
240276 wasWritten = true ;
241277 if (auto pointer = dyn_cast<PointerExpr>(value)) {
242278 valueOS.writeWidth (offset, pointer->getValue ());
243279 baseOS.writeWidth (offset, pointer->getBase ());
280+ taintOS.writeWidth (offset, pointer->getTaint ());
244281 } else {
245282 valueOS.writeWidth (offset, value);
246283 baseOS.writeWidth (
247284 offset, ConstantExpr::create (0 , Context::get ().getPointerWidth ()));
285+ taintOS.writeWidth (offset, Expr::createEmptyTaint ());
248286 }
249287}
250288
@@ -272,17 +310,22 @@ void ObjectState::write8(ref<Expr> offset, ref<Expr> value) {
272310 if (auto pointer = dyn_cast<PointerExpr>(value)) {
273311 valueOS.writeWidth (offset, pointer->getValue ());
274312 baseOS.writeWidth (offset, pointer->getBase ());
313+ taintOS.writeWidth (offset, pointer->getTaint ());
275314 } else {
276315 valueOS.writeWidth (offset, value);
277316 baseOS.writeWidth (
278317 offset, ConstantExpr::create (0 , Context::get ().getPointerWidth ()));
318+ taintOS.writeWidth (offset, Expr::createEmptyTaint ());
279319 }
280320}
281321
282322void ObjectState::write (ref<const ObjectState> os) {
283323 wasWritten = true ;
324+
284325 valueOS.write (os->valueOS );
285326 baseOS.write (os->baseOS );
327+ taintOS.write (os->taintOS );
328+
286329 lastUpdate = os->lastUpdate ;
287330}
288331
@@ -295,20 +338,22 @@ ref<Expr> ObjectState::read(ref<Expr> offset, Expr::Width width) const {
295338
296339 ref<Expr> val = readValue (offset, width);
297340 ref<Expr> base = readBase (offset, width);
298- if (base->isZero ()) {
341+ ref<Expr> taint = readTaint (offset, width);
342+ if (base->isZero () && taint->isZero ()) {
299343 return val;
300344 } else {
301- return PointerExpr::create (base, val);
345+ return PointerExpr::create (base, val, taint );
302346 }
303347}
304348
305349ref<Expr> ObjectState::read (unsigned offset, Expr::Width width) const {
306350 ref<Expr> val = readValue (offset, width);
307351 ref<Expr> base = readBase (offset, width);
308- if (base->isZero ()) {
352+ ref<Expr> taint = readTaint (offset, width);
353+ if (base->isZero () && taint->isZero ()) {
309354 return val;
310355 } else {
311- return PointerExpr::create (base, val);
356+ return PointerExpr::create (base, val, taint );
312357 }
313358}
314359
@@ -368,10 +413,6 @@ ref<Expr> ObjectState::readBase(ref<Expr> offset, Expr::Width width) const {
368413 if (width == Expr::Bool)
369414 return ExtractExpr::create (readBase8 (offset), 0 , Expr::Bool);
370415
371- // Treat bool specially, it is the only non-byte sized write we allow.
372- if (width == Expr::Bool)
373- return ExtractExpr::create (readBase8 (offset), 0 , Expr::Bool);
374-
375416 // Otherwise, follow the slow general case.
376417 unsigned NumBytes = width / 8 ;
377418 assert (width == NumBytes * 8 && " Invalid read size!" );
@@ -416,6 +457,52 @@ ref<Expr> ObjectState::readBase(unsigned offset, Expr::Width width) const {
416457 return Res;
417458}
418459
460+ ref<Expr> ObjectState::readTaint (ref<Expr> offset, Expr::Width width) const {
461+ // Truncate offset to 32-bits.
462+ offset = ZExtExpr::create (offset, Expr::Int32);
463+
464+ // Check for reads at constant offsets.
465+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(offset))
466+ return readTaint (CE->getZExtValue (32 ), width);
467+
468+ // Treat bool specially, it is the only non-byte sized write we allow.
469+ if (width == Expr::Bool)
470+ return ExtractExpr::create (readTaint8 (offset), 0 , Expr::Bool);
471+
472+ // Otherwise, follow the slow general case.
473+ unsigned NumBytes = width / 8 ;
474+ assert (width == NumBytes * 8 && " Invalid read size!" );
475+ ref<Expr> Res (0 );
476+ ref<Expr> null = Expr::createPointer (0 );
477+ for (unsigned i = 0 ; i != NumBytes; ++i) {
478+ unsigned idx = Context::get ().isLittleEndian () ? i : (NumBytes - i - 1 );
479+ ref<Expr> Byte = readTaint8 (
480+ AddExpr::create (offset, ConstantExpr::create (idx, Expr::Int32)));
481+ Res = i ? OrExpr::create (Byte, Res) : Byte;
482+ }
483+
484+ return Res;
485+ }
486+
487+ ref<Expr> ObjectState::readTaint (unsigned offset, Expr::Width width) const {
488+ // Treat bool specially, it is the only non-byte sized write we allow.
489+ if (width == Expr::Bool)
490+ return ExtractExpr::create (readTaint8 (offset), 0 , Expr::Bool);
491+
492+ // Otherwise, follow the slow general case.
493+ unsigned NumBytes = width / 8 ;
494+ assert (width == NumBytes * 8 && " Invalid width for read size!" );
495+ ref<Expr> Res (0 );
496+ ref<Expr> null = Expr::createPointer (0 );
497+ for (unsigned i = 0 ; i != NumBytes; ++i) {
498+ unsigned idx = Context::get ().isLittleEndian () ? i : (NumBytes - i - 1 );
499+ ref<Expr> Byte = readTaint8 (offset + idx);
500+ Res = i ? OrExpr::create (Byte, Res) : Byte;
501+ }
502+
503+ return Res;
504+ }
505+
419506void ObjectState::write (ref<Expr> offset, ref<Expr> value) {
420507 // Truncate offset to 32-bits.
421508 offset = ZExtExpr::create (offset, Expr::Int32);
@@ -516,6 +603,8 @@ void ObjectState::print() const {
516603 valueOS.print ();
517604 llvm::errs () << " \t Offset ObjectStage:\n " ;
518605 baseOS.print ();
606+ llvm::errs () << " \t Taint ObjectStage:\n " ;
607+ taintOS.print ();
519608}
520609
521610KType *ObjectState::getDynamicType () const { return dynamicType; }
0 commit comments