1 //== RangeConstraintManager.cpp - Manage range constraints.------*- C++ -*--==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines RangeConstraintManager, a class that tracks simple 10 // equality and inequality constraints on symbolic values of ProgramState. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Basic/JsonSupport.h" 15 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h" 20 #include "llvm/ADT/FoldingSet.h" 21 #include "llvm/ADT/ImmutableSet.h" 22 #include "llvm/Support/raw_ostream.h" 23 24 using namespace clang; 25 using namespace ento; 26 27 //===----------------------------------------------------------------------===// 28 // RangeSet implementation 29 //===----------------------------------------------------------------------===// 30 31 void RangeSet::IntersectInRange(BasicValueFactory &BV, Factory &F, 32 const llvm::APSInt &Lower, 33 const llvm::APSInt &Upper, 34 PrimRangeSet &newRanges, 35 PrimRangeSet::iterator &i, 36 PrimRangeSet::iterator &e) const { 37 // There are six cases for each range R in the set: 38 // 1. R is entirely before the intersection range. 39 // 2. R is entirely after the intersection range. 40 // 3. R contains the entire intersection range. 41 // 4. R starts before the intersection range and ends in the middle. 42 // 5. R starts in the middle of the intersection range and ends after it. 43 // 6. R is entirely contained in the intersection range. 44 // These correspond to each of the conditions below. 45 for (/* i = begin(), e = end() */; i != e; ++i) { 46 if (i->To() < Lower) { 47 continue; 48 } 49 if (i->From() > Upper) { 50 break; 51 } 52 53 if (i->Includes(Lower)) { 54 if (i->Includes(Upper)) { 55 newRanges = 56 F.add(newRanges, Range(BV.getValue(Lower), BV.getValue(Upper))); 57 break; 58 } else 59 newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To())); 60 } else { 61 if (i->Includes(Upper)) { 62 newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper))); 63 break; 64 } else 65 newRanges = F.add(newRanges, *i); 66 } 67 } 68 } 69 70 const llvm::APSInt &RangeSet::getMinValue() const { 71 assert(!isEmpty()); 72 return begin()->From(); 73 } 74 75 const llvm::APSInt &RangeSet::getMaxValue() const { 76 assert(!isEmpty()); 77 // NOTE: It's a shame that we can't implement 'getMaxValue' without scanning 78 // the whole tree to get to the last element. 79 // llvm::ImmutableSet should support decrement for 'end' iterators 80 // or reverse order iteration. 81 auto It = begin(); 82 for (auto End = end(); std::next(It) != End; ++It) { 83 } 84 return It->To(); 85 } 86 87 bool RangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const { 88 if (isEmpty()) { 89 // This range is already infeasible. 90 return false; 91 } 92 93 // This function has nine cases, the cartesian product of range-testing 94 // both the upper and lower bounds against the symbol's type. 95 // Each case requires a different pinning operation. 96 // The function returns false if the described range is entirely outside 97 // the range of values for the associated symbol. 98 APSIntType Type(getMinValue()); 99 APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true); 100 APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true); 101 102 switch (LowerTest) { 103 case APSIntType::RTR_Below: 104 switch (UpperTest) { 105 case APSIntType::RTR_Below: 106 // The entire range is outside the symbol's set of possible values. 107 // If this is a conventionally-ordered range, the state is infeasible. 108 if (Lower <= Upper) 109 return false; 110 111 // However, if the range wraps around, it spans all possible values. 112 Lower = Type.getMinValue(); 113 Upper = Type.getMaxValue(); 114 break; 115 case APSIntType::RTR_Within: 116 // The range starts below what's possible but ends within it. Pin. 117 Lower = Type.getMinValue(); 118 Type.apply(Upper); 119 break; 120 case APSIntType::RTR_Above: 121 // The range spans all possible values for the symbol. Pin. 122 Lower = Type.getMinValue(); 123 Upper = Type.getMaxValue(); 124 break; 125 } 126 break; 127 case APSIntType::RTR_Within: 128 switch (UpperTest) { 129 case APSIntType::RTR_Below: 130 // The range wraps around, but all lower values are not possible. 131 Type.apply(Lower); 132 Upper = Type.getMaxValue(); 133 break; 134 case APSIntType::RTR_Within: 135 // The range may or may not wrap around, but both limits are valid. 136 Type.apply(Lower); 137 Type.apply(Upper); 138 break; 139 case APSIntType::RTR_Above: 140 // The range starts within what's possible but ends above it. Pin. 141 Type.apply(Lower); 142 Upper = Type.getMaxValue(); 143 break; 144 } 145 break; 146 case APSIntType::RTR_Above: 147 switch (UpperTest) { 148 case APSIntType::RTR_Below: 149 // The range wraps but is outside the symbol's set of possible values. 150 return false; 151 case APSIntType::RTR_Within: 152 // The range starts above what's possible but ends within it (wrap). 153 Lower = Type.getMinValue(); 154 Type.apply(Upper); 155 break; 156 case APSIntType::RTR_Above: 157 // The entire range is outside the symbol's set of possible values. 158 // If this is a conventionally-ordered range, the state is infeasible. 159 if (Lower <= Upper) 160 return false; 161 162 // However, if the range wraps around, it spans all possible values. 163 Lower = Type.getMinValue(); 164 Upper = Type.getMaxValue(); 165 break; 166 } 167 break; 168 } 169 170 return true; 171 } 172 173 // Returns a set containing the values in the receiving set, intersected with 174 // the closed range [Lower, Upper]. Unlike the Range type, this range uses 175 // modular arithmetic, corresponding to the common treatment of C integer 176 // overflow. Thus, if the Lower bound is greater than the Upper bound, the 177 // range is taken to wrap around. This is equivalent to taking the 178 // intersection with the two ranges [Min, Upper] and [Lower, Max], 179 // or, alternatively, /removing/ all integers between Upper and Lower. 180 RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F, 181 llvm::APSInt Lower, llvm::APSInt Upper) const { 182 PrimRangeSet newRanges = F.getEmptySet(); 183 184 if (isEmpty() || !pin(Lower, Upper)) 185 return newRanges; 186 187 PrimRangeSet::iterator i = begin(), e = end(); 188 if (Lower <= Upper) 189 IntersectInRange(BV, F, Lower, Upper, newRanges, i, e); 190 else { 191 // The order of the next two statements is important! 192 // IntersectInRange() does not reset the iteration state for i and e. 193 // Therefore, the lower range most be handled first. 194 IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e); 195 IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e); 196 } 197 198 return newRanges; 199 } 200 201 // Returns a set containing the values in the receiving set, intersected with 202 // the range set passed as parameter. 203 RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F, 204 const RangeSet &Other) const { 205 PrimRangeSet newRanges = F.getEmptySet(); 206 207 for (iterator i = Other.begin(), e = Other.end(); i != e; ++i) { 208 RangeSet newPiece = Intersect(BV, F, i->From(), i->To()); 209 for (iterator j = newPiece.begin(), ee = newPiece.end(); j != ee; ++j) { 210 newRanges = F.add(newRanges, *j); 211 } 212 } 213 214 return newRanges; 215 } 216 217 // Turn all [A, B] ranges to [-B, -A], when "-" is a C-like unary minus 218 // operation under the values of the type. 219 // 220 // We also handle MIN because applying unary minus to MIN does not change it. 221 // Example 1: 222 // char x = -128; // -128 is a MIN value in a range of 'char' 223 // char y = -x; // y: -128 224 // Example 2: 225 // unsigned char x = 0; // 0 is a MIN value in a range of 'unsigned char' 226 // unsigned char y = -x; // y: 0 227 // 228 // And it makes us to separate the range 229 // like [MIN, N] to [MIN, MIN] U [-N,MAX]. 230 // For instance, whole range is {-128..127} and subrange is [-128,-126], 231 // thus [-128,-127,-126,.....] negates to [-128,.....,126,127]. 232 // 233 // Negate restores disrupted ranges on bounds, 234 // e.g. [MIN, B] => [MIN, MIN] U [-B, MAX] => [MIN, B]. 235 RangeSet RangeSet::Negate(BasicValueFactory &BV, Factory &F) const { 236 PrimRangeSet newRanges = F.getEmptySet(); 237 238 if (isEmpty()) 239 return newRanges; 240 241 const llvm::APSInt sampleValue = getMinValue(); 242 const llvm::APSInt &MIN = BV.getMinValue(sampleValue); 243 const llvm::APSInt &MAX = BV.getMaxValue(sampleValue); 244 245 // Handle a special case for MIN value. 246 iterator i = begin(); 247 const llvm::APSInt &from = i->From(); 248 const llvm::APSInt &to = i->To(); 249 if (from == MIN) { 250 // If [from, to] are [MIN, MAX], then just return the same [MIN, MAX]. 251 if (to == MAX) { 252 newRanges = ranges; 253 } else { 254 // Add separate range for the lowest value. 255 newRanges = F.add(newRanges, Range(MIN, MIN)); 256 // Skip adding the second range in case when [from, to] are [MIN, MIN]. 257 if (to != MIN) { 258 newRanges = F.add(newRanges, Range(BV.getValue(-to), MAX)); 259 } 260 } 261 // Skip the first range in the loop. 262 ++i; 263 } 264 265 // Negate all other ranges. 266 for (iterator e = end(); i != e; ++i) { 267 // Negate int values. 268 const llvm::APSInt &newFrom = BV.getValue(-i->To()); 269 const llvm::APSInt &newTo = BV.getValue(-i->From()); 270 // Add a negated range. 271 newRanges = F.add(newRanges, Range(newFrom, newTo)); 272 } 273 274 if (newRanges.isSingleton()) 275 return newRanges; 276 277 // Try to find and unite next ranges: 278 // [MIN, MIN] & [MIN + 1, N] => [MIN, N]. 279 iterator iter1 = newRanges.begin(); 280 iterator iter2 = std::next(iter1); 281 282 if (iter1->To() == MIN && (iter2->From() - 1) == MIN) { 283 const llvm::APSInt &to = iter2->To(); 284 // remove adjacent ranges 285 newRanges = F.remove(newRanges, *iter1); 286 newRanges = F.remove(newRanges, *newRanges.begin()); 287 // add united range 288 newRanges = F.add(newRanges, Range(MIN, to)); 289 } 290 291 return newRanges; 292 } 293 294 void RangeSet::print(raw_ostream &os) const { 295 bool isFirst = true; 296 os << "{ "; 297 for (iterator i = begin(), e = end(); i != e; ++i) { 298 if (isFirst) 299 isFirst = false; 300 else 301 os << ", "; 302 303 os << '[' << i->From().toString(10) << ", " << i->To().toString(10) 304 << ']'; 305 } 306 os << " }"; 307 } 308 309 namespace { 310 311 /// A little component aggregating all of the reasoning we have about 312 /// the ranges of symbolic expressions. 313 /// 314 /// Even when we don't know the exact values of the operands, we still 315 /// can get a pretty good estimate of the result's range. 316 class SymbolicRangeInferrer 317 : public SymExprVisitor<SymbolicRangeInferrer, RangeSet> { 318 public: 319 static RangeSet inferRange(BasicValueFactory &BV, RangeSet::Factory &F, 320 ProgramStateRef State, SymbolRef Sym) { 321 SymbolicRangeInferrer Inferrer(BV, F, State); 322 return Inferrer.infer(Sym); 323 } 324 325 RangeSet VisitSymExpr(SymbolRef Sym) { 326 // If we got to this function, the actual type of the symbolic 327 // expression is not supported for advanced inference. 328 // In this case, we simply backoff to the default "let's simply 329 // infer the range from the expression's type". 330 return infer(Sym->getType()); 331 } 332 333 RangeSet VisitSymIntExpr(const SymIntExpr *Sym) { 334 return VisitBinaryOperator(Sym); 335 } 336 337 RangeSet VisitIntSymExpr(const IntSymExpr *Sym) { 338 return VisitBinaryOperator(Sym); 339 } 340 341 RangeSet VisitSymSymExpr(const SymSymExpr *Sym) { 342 return VisitBinaryOperator(Sym); 343 } 344 345 private: 346 SymbolicRangeInferrer(BasicValueFactory &BV, RangeSet::Factory &F, 347 ProgramStateRef S) 348 : ValueFactory(BV), RangeFactory(F), State(S) {} 349 350 /// Infer range information from the given integer constant. 351 /// 352 /// It's not a real "inference", but is here for operating with 353 /// sub-expressions in a more polymorphic manner. 354 RangeSet inferAs(const llvm::APSInt &Val, QualType) { 355 return {RangeFactory, Val}; 356 } 357 358 /// Infer range information from symbol in the context of the given type. 359 RangeSet inferAs(SymbolRef Sym, QualType DestType) { 360 QualType ActualType = Sym->getType(); 361 // Check that we can reason about the symbol at all. 362 if (ActualType->isIntegralOrEnumerationType() || 363 Loc::isLocType(ActualType)) { 364 return infer(Sym); 365 } 366 // Otherwise, let's simply infer from the destination type. 367 // We couldn't figure out nothing else about that expression. 368 return infer(DestType); 369 } 370 371 RangeSet infer(SymbolRef Sym) { 372 const RangeSet *AssociatedRange = State->get<ConstraintRange>(Sym); 373 374 // If Sym is a difference of symbols A - B, then maybe we have range set 375 // stored for B - A. 376 const RangeSet *RangeAssociatedWithNegatedSym = 377 getRangeForMinusSymbol(State, Sym); 378 379 // If we have range set stored for both A - B and B - A then calculate the 380 // effective range set by intersecting the range set for A - B and the 381 // negated range set of B - A. 382 if (AssociatedRange && RangeAssociatedWithNegatedSym) 383 return AssociatedRange->Intersect( 384 ValueFactory, RangeFactory, 385 RangeAssociatedWithNegatedSym->Negate(ValueFactory, RangeFactory)); 386 387 if (AssociatedRange) 388 return *AssociatedRange; 389 390 if (RangeAssociatedWithNegatedSym) 391 return RangeAssociatedWithNegatedSym->Negate(ValueFactory, RangeFactory); 392 393 return Visit(Sym); 394 } 395 396 /// Infer range information solely from the type. 397 RangeSet infer(QualType T) { 398 // Lazily generate a new RangeSet representing all possible values for the 399 // given symbol type. 400 RangeSet Result(RangeFactory, ValueFactory.getMinValue(T), 401 ValueFactory.getMaxValue(T)); 402 403 // References are known to be non-zero. 404 if (T->isReferenceType()) 405 return assumeNonZero(Result, T); 406 407 return Result; 408 } 409 410 template <class BinarySymExprTy> 411 RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) { 412 // TODO #1: VisitBinaryOperator implementation might not make a good 413 // use of the inferred ranges. In this case, we might be calculating 414 // everything for nothing. This being said, we should introduce some 415 // sort of laziness mechanism here. 416 // 417 // TODO #2: We didn't go into the nested expressions before, so it 418 // might cause us spending much more time doing the inference. 419 // This can be a problem for deeply nested expressions that are 420 // involved in conditions and get tested continuously. We definitely 421 // need to address this issue and introduce some sort of caching 422 // in here. 423 QualType ResultType = Sym->getType(); 424 return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType), 425 Sym->getOpcode(), 426 inferAs(Sym->getRHS(), ResultType), ResultType); 427 } 428 429 RangeSet VisitBinaryOperator(RangeSet LHS, BinaryOperator::Opcode Op, 430 RangeSet RHS, QualType T) { 431 switch (Op) { 432 case BO_Or: 433 return VisitBinaryOperator<BO_Or>(LHS, RHS, T); 434 case BO_And: 435 return VisitBinaryOperator<BO_And>(LHS, RHS, T); 436 case BO_Rem: 437 return VisitBinaryOperator<BO_Rem>(LHS, RHS, T); 438 default: 439 return infer(T); 440 } 441 } 442 443 //===----------------------------------------------------------------------===// 444 // Ranges and operators 445 //===----------------------------------------------------------------------===// 446 447 /// Return a rough approximation of the given range set. 448 /// 449 /// For the range set: 450 /// { [x_0, y_0], [x_1, y_1], ... , [x_N, y_N] } 451 /// it will return the range [x_0, y_N]. 452 static Range fillGaps(RangeSet Origin) { 453 assert(!Origin.isEmpty()); 454 return {Origin.getMinValue(), Origin.getMaxValue()}; 455 } 456 457 /// Try to convert given range into the given type. 458 /// 459 /// It will return llvm::None only when the trivial conversion is possible. 460 llvm::Optional<Range> convert(const Range &Origin, APSIntType To) { 461 if (To.testInRange(Origin.From(), false) != APSIntType::RTR_Within || 462 To.testInRange(Origin.To(), false) != APSIntType::RTR_Within) { 463 return llvm::None; 464 } 465 return Range(ValueFactory.Convert(To, Origin.From()), 466 ValueFactory.Convert(To, Origin.To())); 467 } 468 469 template <BinaryOperator::Opcode Op> 470 RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) { 471 // We should propagate information about unfeasbility of one of the 472 // operands to the resulting range. 473 if (LHS.isEmpty() || RHS.isEmpty()) { 474 return RangeFactory.getEmptySet(); 475 } 476 477 Range CoarseLHS = fillGaps(LHS); 478 Range CoarseRHS = fillGaps(RHS); 479 480 APSIntType ResultType = ValueFactory.getAPSIntType(T); 481 482 // We need to convert ranges to the resulting type, so we can compare values 483 // and combine them in a meaningful (in terms of the given operation) way. 484 auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType); 485 auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType); 486 487 // It is hard to reason about ranges when conversion changes 488 // borders of the ranges. 489 if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) { 490 return infer(T); 491 } 492 493 return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T); 494 } 495 496 template <BinaryOperator::Opcode Op> 497 RangeSet VisitBinaryOperator(Range LHS, Range RHS, QualType T) { 498 return infer(T); 499 } 500 501 /// Return a symmetrical range for the given range and type. 502 /// 503 /// If T is signed, return the smallest range [-x..x] that covers the original 504 /// range, or [-min(T), max(T)] if the aforementioned symmetric range doesn't 505 /// exist due to original range covering min(T)). 506 /// 507 /// If T is unsigned, return the smallest range [0..x] that covers the 508 /// original range. 509 Range getSymmetricalRange(Range Origin, QualType T) { 510 APSIntType RangeType = ValueFactory.getAPSIntType(T); 511 512 if (RangeType.isUnsigned()) { 513 return Range(ValueFactory.getMinValue(RangeType), Origin.To()); 514 } 515 516 if (Origin.From().isMinSignedValue()) { 517 // If mini is a minimal signed value, absolute value of it is greater 518 // than the maximal signed value. In order to avoid these 519 // complications, we simply return the whole range. 520 return {ValueFactory.getMinValue(RangeType), 521 ValueFactory.getMaxValue(RangeType)}; 522 } 523 524 // At this point, we are sure that the type is signed and we can safely 525 // use unary - operator. 526 // 527 // While calculating absolute maximum, we can use the following formula 528 // because of these reasons: 529 // * If From >= 0 then To >= From and To >= -From. 530 // AbsMax == To == max(To, -From) 531 // * If To <= 0 then -From >= -To and -From >= From. 532 // AbsMax == -From == max(-From, To) 533 // * Otherwise, From <= 0, To >= 0, and 534 // AbsMax == max(abs(From), abs(To)) 535 llvm::APSInt AbsMax = std::max(-Origin.From(), Origin.To()); 536 537 // Intersection is guaranteed to be non-empty. 538 return {ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)}; 539 } 540 541 /// Return a range set subtracting zero from \p Domain. 542 RangeSet assumeNonZero(RangeSet Domain, QualType T) { 543 APSIntType IntType = ValueFactory.getAPSIntType(T); 544 return Domain.Intersect(ValueFactory, RangeFactory, 545 ++IntType.getZeroValue(), --IntType.getZeroValue()); 546 } 547 548 // FIXME: Once SValBuilder supports unary minus, we should use SValBuilder to 549 // obtain the negated symbolic expression instead of constructing the 550 // symbol manually. This will allow us to support finding ranges of not 551 // only negated SymSymExpr-type expressions, but also of other, simpler 552 // expressions which we currently do not know how to negate. 553 const RangeSet *getRangeForMinusSymbol(ProgramStateRef State, SymbolRef Sym) { 554 if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) { 555 if (SSE->getOpcode() == BO_Sub) { 556 QualType T = Sym->getType(); 557 SymbolManager &SymMgr = State->getSymbolManager(); 558 SymbolRef negSym = 559 SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), T); 560 561 if (const RangeSet *negV = State->get<ConstraintRange>(negSym)) { 562 // Unsigned range set cannot be negated, unless it is [0, 0]. 563 if (T->isUnsignedIntegerOrEnumerationType() || 564 T->isSignedIntegerOrEnumerationType()) 565 return negV; 566 } 567 } 568 } 569 return nullptr; 570 } 571 572 BasicValueFactory &ValueFactory; 573 RangeSet::Factory &RangeFactory; 574 ProgramStateRef State; 575 }; 576 577 template <> 578 RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Or>(Range LHS, Range RHS, 579 QualType T) { 580 APSIntType ResultType = ValueFactory.getAPSIntType(T); 581 llvm::APSInt Zero = ResultType.getZeroValue(); 582 583 bool IsLHSPositiveOrZero = LHS.From() >= Zero; 584 bool IsRHSPositiveOrZero = RHS.From() >= Zero; 585 586 bool IsLHSNegative = LHS.To() < Zero; 587 bool IsRHSNegative = RHS.To() < Zero; 588 589 // Check if both ranges have the same sign. 590 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) || 591 (IsLHSNegative && IsRHSNegative)) { 592 // The result is definitely greater or equal than any of the operands. 593 const llvm::APSInt &Min = std::max(LHS.From(), RHS.From()); 594 595 // We estimate maximal value for positives as the maximal value for the 596 // given type. For negatives, we estimate it with -1 (e.g. 0x11111111). 597 // 598 // TODO: We basically, limit the resulting range from below, but don't do 599 // anything with the upper bound. 600 // 601 // For positive operands, it can be done as follows: for the upper 602 // bound of LHS and RHS we calculate the most significant bit set. 603 // Let's call it the N-th bit. Then we can estimate the maximal 604 // number to be 2^(N+1)-1, i.e. the number with all the bits up to 605 // the N-th bit set. 606 const llvm::APSInt &Max = IsLHSNegative 607 ? ValueFactory.getValue(--Zero) 608 : ValueFactory.getMaxValue(ResultType); 609 610 return {RangeFactory, ValueFactory.getValue(Min), Max}; 611 } 612 613 // Otherwise, let's check if at least one of the operands is negative. 614 if (IsLHSNegative || IsRHSNegative) { 615 // This means that the result is definitely negative as well. 616 return {RangeFactory, ValueFactory.getMinValue(ResultType), 617 ValueFactory.getValue(--Zero)}; 618 } 619 620 RangeSet DefaultRange = infer(T); 621 622 // It is pretty hard to reason about operands with different signs 623 // (and especially with possibly different signs). We simply check if it 624 // can be zero. In order to conclude that the result could not be zero, 625 // at least one of the operands should be definitely not zero itself. 626 if (!LHS.Includes(Zero) || !RHS.Includes(Zero)) { 627 return assumeNonZero(DefaultRange, T); 628 } 629 630 // Nothing much else to do here. 631 return DefaultRange; 632 } 633 634 template <> 635 RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_And>(Range LHS, 636 Range RHS, 637 QualType T) { 638 APSIntType ResultType = ValueFactory.getAPSIntType(T); 639 llvm::APSInt Zero = ResultType.getZeroValue(); 640 641 bool IsLHSPositiveOrZero = LHS.From() >= Zero; 642 bool IsRHSPositiveOrZero = RHS.From() >= Zero; 643 644 bool IsLHSNegative = LHS.To() < Zero; 645 bool IsRHSNegative = RHS.To() < Zero; 646 647 // Check if both ranges have the same sign. 648 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) || 649 (IsLHSNegative && IsRHSNegative)) { 650 // The result is definitely less or equal than any of the operands. 651 const llvm::APSInt &Max = std::min(LHS.To(), RHS.To()); 652 653 // We conservatively estimate lower bound to be the smallest positive 654 // or negative value corresponding to the sign of the operands. 655 const llvm::APSInt &Min = IsLHSNegative 656 ? ValueFactory.getMinValue(ResultType) 657 : ValueFactory.getValue(Zero); 658 659 return {RangeFactory, Min, Max}; 660 } 661 662 // Otherwise, let's check if at least one of the operands is positive. 663 if (IsLHSPositiveOrZero || IsRHSPositiveOrZero) { 664 // This makes result definitely positive. 665 // 666 // We can also reason about a maximal value by finding the maximal 667 // value of the positive operand. 668 const llvm::APSInt &Max = IsLHSPositiveOrZero ? LHS.To() : RHS.To(); 669 670 // The minimal value on the other hand is much harder to reason about. 671 // The only thing we know for sure is that the result is positive. 672 return {RangeFactory, ValueFactory.getValue(Zero), 673 ValueFactory.getValue(Max)}; 674 } 675 676 // Nothing much else to do here. 677 return infer(T); 678 } 679 680 template <> 681 RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(Range LHS, 682 Range RHS, 683 QualType T) { 684 llvm::APSInt Zero = ValueFactory.getAPSIntType(T).getZeroValue(); 685 686 Range ConservativeRange = getSymmetricalRange(RHS, T); 687 688 llvm::APSInt Max = ConservativeRange.To(); 689 llvm::APSInt Min = ConservativeRange.From(); 690 691 if (Max == Zero) { 692 // It's an undefined behaviour to divide by 0 and it seems like we know 693 // for sure that RHS is 0. Let's say that the resulting range is 694 // simply infeasible for that matter. 695 return RangeFactory.getEmptySet(); 696 } 697 698 // At this point, our conservative range is closed. The result, however, 699 // couldn't be greater than the RHS' maximal absolute value. Because of 700 // this reason, we turn the range into open (or half-open in case of 701 // unsigned integers). 702 // 703 // While we operate on integer values, an open interval (a, b) can be easily 704 // represented by the closed interval [a + 1, b - 1]. And this is exactly 705 // what we do next. 706 // 707 // If we are dealing with unsigned case, we shouldn't move the lower bound. 708 if (Min.isSigned()) { 709 ++Min; 710 } 711 --Max; 712 713 bool IsLHSPositiveOrZero = LHS.From() >= Zero; 714 bool IsRHSPositiveOrZero = RHS.From() >= Zero; 715 716 // Remainder operator results with negative operands is implementation 717 // defined. Positive cases are much easier to reason about though. 718 if (IsLHSPositiveOrZero && IsRHSPositiveOrZero) { 719 // If maximal value of LHS is less than maximal value of RHS, 720 // the result won't get greater than LHS.To(). 721 Max = std::min(LHS.To(), Max); 722 // We want to check if it is a situation similar to the following: 723 // 724 // <------------|---[ LHS ]--------[ RHS ]-----> 725 // -INF 0 +INF 726 // 727 // In this situation, we can conclude that (LHS / RHS) == 0 and 728 // (LHS % RHS) == LHS. 729 Min = LHS.To() < RHS.From() ? LHS.From() : Zero; 730 } 731 732 // Nevertheless, the symmetrical range for RHS is a conservative estimate 733 // for any sign of either LHS, or RHS. 734 return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)}; 735 } 736 737 class RangeConstraintManager : public RangedConstraintManager { 738 public: 739 RangeConstraintManager(ExprEngine *EE, SValBuilder &SVB) 740 : RangedConstraintManager(EE, SVB) {} 741 742 //===------------------------------------------------------------------===// 743 // Implementation for interface from ConstraintManager. 744 //===------------------------------------------------------------------===// 745 746 bool haveEqualConstraints(ProgramStateRef S1, 747 ProgramStateRef S2) const override { 748 return S1->get<ConstraintRange>() == S2->get<ConstraintRange>(); 749 } 750 751 bool canReasonAbout(SVal X) const override; 752 753 ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; 754 755 const llvm::APSInt *getSymVal(ProgramStateRef State, 756 SymbolRef Sym) const override; 757 758 ProgramStateRef removeDeadBindings(ProgramStateRef State, 759 SymbolReaper &SymReaper) override; 760 761 void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n", 762 unsigned int Space = 0, bool IsDot = false) const override; 763 764 //===------------------------------------------------------------------===// 765 // Implementation for interface from RangedConstraintManager. 766 //===------------------------------------------------------------------===// 767 768 ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, 769 const llvm::APSInt &V, 770 const llvm::APSInt &Adjustment) override; 771 772 ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, 773 const llvm::APSInt &V, 774 const llvm::APSInt &Adjustment) override; 775 776 ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, 777 const llvm::APSInt &V, 778 const llvm::APSInt &Adjustment) override; 779 780 ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, 781 const llvm::APSInt &V, 782 const llvm::APSInt &Adjustment) override; 783 784 ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, 785 const llvm::APSInt &V, 786 const llvm::APSInt &Adjustment) override; 787 788 ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, 789 const llvm::APSInt &V, 790 const llvm::APSInt &Adjustment) override; 791 792 ProgramStateRef assumeSymWithinInclusiveRange( 793 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 794 const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; 795 796 ProgramStateRef assumeSymOutsideInclusiveRange( 797 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 798 const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; 799 800 private: 801 RangeSet::Factory F; 802 803 RangeSet getRange(ProgramStateRef State, SymbolRef Sym); 804 805 RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, 806 const llvm::APSInt &Int, 807 const llvm::APSInt &Adjustment); 808 RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym, 809 const llvm::APSInt &Int, 810 const llvm::APSInt &Adjustment); 811 RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym, 812 const llvm::APSInt &Int, 813 const llvm::APSInt &Adjustment); 814 RangeSet getSymLERange(llvm::function_ref<RangeSet()> RS, 815 const llvm::APSInt &Int, 816 const llvm::APSInt &Adjustment); 817 RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, 818 const llvm::APSInt &Int, 819 const llvm::APSInt &Adjustment); 820 }; 821 822 } // end anonymous namespace 823 824 std::unique_ptr<ConstraintManager> 825 ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, 826 ExprEngine *Eng) { 827 return std::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder()); 828 } 829 830 bool RangeConstraintManager::canReasonAbout(SVal X) const { 831 Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>(); 832 if (SymVal && SymVal->isExpression()) { 833 const SymExpr *SE = SymVal->getSymbol(); 834 835 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) { 836 switch (SIE->getOpcode()) { 837 // We don't reason yet about bitwise-constraints on symbolic values. 838 case BO_And: 839 case BO_Or: 840 case BO_Xor: 841 return false; 842 // We don't reason yet about these arithmetic constraints on 843 // symbolic values. 844 case BO_Mul: 845 case BO_Div: 846 case BO_Rem: 847 case BO_Shl: 848 case BO_Shr: 849 return false; 850 // All other cases. 851 default: 852 return true; 853 } 854 } 855 856 if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) { 857 // FIXME: Handle <=> here. 858 if (BinaryOperator::isEqualityOp(SSE->getOpcode()) || 859 BinaryOperator::isRelationalOp(SSE->getOpcode())) { 860 // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc. 861 // We've recently started producing Loc <> NonLoc comparisons (that 862 // result from casts of one of the operands between eg. intptr_t and 863 // void *), but we can't reason about them yet. 864 if (Loc::isLocType(SSE->getLHS()->getType())) { 865 return Loc::isLocType(SSE->getRHS()->getType()); 866 } 867 } 868 } 869 870 return false; 871 } 872 873 return true; 874 } 875 876 ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State, 877 SymbolRef Sym) { 878 const RangeSet *Ranges = State->get<ConstraintRange>(Sym); 879 880 // If we don't have any information about this symbol, it's underconstrained. 881 if (!Ranges) 882 return ConditionTruthVal(); 883 884 // If we have a concrete value, see if it's zero. 885 if (const llvm::APSInt *Value = Ranges->getConcreteValue()) 886 return *Value == 0; 887 888 BasicValueFactory &BV = getBasicVals(); 889 APSIntType IntType = BV.getAPSIntType(Sym->getType()); 890 llvm::APSInt Zero = IntType.getZeroValue(); 891 892 // Check if zero is in the set of possible values. 893 if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty()) 894 return false; 895 896 // Zero is a possible value, but it is not the /only/ possible value. 897 return ConditionTruthVal(); 898 } 899 900 const llvm::APSInt *RangeConstraintManager::getSymVal(ProgramStateRef St, 901 SymbolRef Sym) const { 902 const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(Sym); 903 return T ? T->getConcreteValue() : nullptr; 904 } 905 906 /// Scan all symbols referenced by the constraints. If the symbol is not alive 907 /// as marked in LSymbols, mark it as dead in DSymbols. 908 ProgramStateRef 909 RangeConstraintManager::removeDeadBindings(ProgramStateRef State, 910 SymbolReaper &SymReaper) { 911 bool Changed = false; 912 ConstraintRangeTy CR = State->get<ConstraintRange>(); 913 ConstraintRangeTy::Factory &CRFactory = State->get_context<ConstraintRange>(); 914 915 for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) { 916 SymbolRef Sym = I.getKey(); 917 if (SymReaper.isDead(Sym)) { 918 Changed = true; 919 CR = CRFactory.remove(CR, Sym); 920 } 921 } 922 923 return Changed ? State->set<ConstraintRange>(CR) : State; 924 } 925 926 RangeSet RangeConstraintManager::getRange(ProgramStateRef State, 927 SymbolRef Sym) { 928 return SymbolicRangeInferrer::inferRange(getBasicVals(), F, State, Sym); 929 } 930 931 //===------------------------------------------------------------------------=== 932 // assumeSymX methods: protected interface for RangeConstraintManager. 933 //===------------------------------------------------------------------------===/ 934 935 // The syntax for ranges below is mathematical, using [x, y] for closed ranges 936 // and (x, y) for open ranges. These ranges are modular, corresponding with 937 // a common treatment of C integer overflow. This means that these methods 938 // do not have to worry about overflow; RangeSet::Intersect can handle such a 939 // "wraparound" range. 940 // As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1, 941 // UINT_MAX, 0, 1, and 2. 942 943 ProgramStateRef 944 RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, 945 const llvm::APSInt &Int, 946 const llvm::APSInt &Adjustment) { 947 // Before we do any real work, see if the value can even show up. 948 APSIntType AdjustmentType(Adjustment); 949 if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) 950 return St; 951 952 llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment; 953 llvm::APSInt Upper = Lower; 954 --Lower; 955 ++Upper; 956 957 // [Int-Adjustment+1, Int-Adjustment-1] 958 // Notice that the lower bound is greater than the upper bound. 959 RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower); 960 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 961 } 962 963 ProgramStateRef 964 RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, 965 const llvm::APSInt &Int, 966 const llvm::APSInt &Adjustment) { 967 // Before we do any real work, see if the value can even show up. 968 APSIntType AdjustmentType(Adjustment); 969 if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) 970 return nullptr; 971 972 // [Int-Adjustment, Int-Adjustment] 973 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment; 974 RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt); 975 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 976 } 977 978 RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St, 979 SymbolRef Sym, 980 const llvm::APSInt &Int, 981 const llvm::APSInt &Adjustment) { 982 // Before we do any real work, see if the value can even show up. 983 APSIntType AdjustmentType(Adjustment); 984 switch (AdjustmentType.testInRange(Int, true)) { 985 case APSIntType::RTR_Below: 986 return F.getEmptySet(); 987 case APSIntType::RTR_Within: 988 break; 989 case APSIntType::RTR_Above: 990 return getRange(St, Sym); 991 } 992 993 // Special case for Int == Min. This is always false. 994 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 995 llvm::APSInt Min = AdjustmentType.getMinValue(); 996 if (ComparisonVal == Min) 997 return F.getEmptySet(); 998 999 llvm::APSInt Lower = Min - Adjustment; 1000 llvm::APSInt Upper = ComparisonVal - Adjustment; 1001 --Upper; 1002 1003 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 1004 } 1005 1006 ProgramStateRef 1007 RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym, 1008 const llvm::APSInt &Int, 1009 const llvm::APSInt &Adjustment) { 1010 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment); 1011 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 1012 } 1013 1014 RangeSet RangeConstraintManager::getSymGTRange(ProgramStateRef St, 1015 SymbolRef Sym, 1016 const llvm::APSInt &Int, 1017 const llvm::APSInt &Adjustment) { 1018 // Before we do any real work, see if the value can even show up. 1019 APSIntType AdjustmentType(Adjustment); 1020 switch (AdjustmentType.testInRange(Int, true)) { 1021 case APSIntType::RTR_Below: 1022 return getRange(St, Sym); 1023 case APSIntType::RTR_Within: 1024 break; 1025 case APSIntType::RTR_Above: 1026 return F.getEmptySet(); 1027 } 1028 1029 // Special case for Int == Max. This is always false. 1030 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 1031 llvm::APSInt Max = AdjustmentType.getMaxValue(); 1032 if (ComparisonVal == Max) 1033 return F.getEmptySet(); 1034 1035 llvm::APSInt Lower = ComparisonVal - Adjustment; 1036 llvm::APSInt Upper = Max - Adjustment; 1037 ++Lower; 1038 1039 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 1040 } 1041 1042 ProgramStateRef 1043 RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym, 1044 const llvm::APSInt &Int, 1045 const llvm::APSInt &Adjustment) { 1046 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment); 1047 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 1048 } 1049 1050 RangeSet RangeConstraintManager::getSymGERange(ProgramStateRef St, 1051 SymbolRef Sym, 1052 const llvm::APSInt &Int, 1053 const llvm::APSInt &Adjustment) { 1054 // Before we do any real work, see if the value can even show up. 1055 APSIntType AdjustmentType(Adjustment); 1056 switch (AdjustmentType.testInRange(Int, true)) { 1057 case APSIntType::RTR_Below: 1058 return getRange(St, Sym); 1059 case APSIntType::RTR_Within: 1060 break; 1061 case APSIntType::RTR_Above: 1062 return F.getEmptySet(); 1063 } 1064 1065 // Special case for Int == Min. This is always feasible. 1066 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 1067 llvm::APSInt Min = AdjustmentType.getMinValue(); 1068 if (ComparisonVal == Min) 1069 return getRange(St, Sym); 1070 1071 llvm::APSInt Max = AdjustmentType.getMaxValue(); 1072 llvm::APSInt Lower = ComparisonVal - Adjustment; 1073 llvm::APSInt Upper = Max - Adjustment; 1074 1075 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 1076 } 1077 1078 ProgramStateRef 1079 RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym, 1080 const llvm::APSInt &Int, 1081 const llvm::APSInt &Adjustment) { 1082 RangeSet New = getSymGERange(St, Sym, Int, Adjustment); 1083 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 1084 } 1085 1086 RangeSet RangeConstraintManager::getSymLERange( 1087 llvm::function_ref<RangeSet()> RS, 1088 const llvm::APSInt &Int, 1089 const llvm::APSInt &Adjustment) { 1090 // Before we do any real work, see if the value can even show up. 1091 APSIntType AdjustmentType(Adjustment); 1092 switch (AdjustmentType.testInRange(Int, true)) { 1093 case APSIntType::RTR_Below: 1094 return F.getEmptySet(); 1095 case APSIntType::RTR_Within: 1096 break; 1097 case APSIntType::RTR_Above: 1098 return RS(); 1099 } 1100 1101 // Special case for Int == Max. This is always feasible. 1102 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 1103 llvm::APSInt Max = AdjustmentType.getMaxValue(); 1104 if (ComparisonVal == Max) 1105 return RS(); 1106 1107 llvm::APSInt Min = AdjustmentType.getMinValue(); 1108 llvm::APSInt Lower = Min - Adjustment; 1109 llvm::APSInt Upper = ComparisonVal - Adjustment; 1110 1111 return RS().Intersect(getBasicVals(), F, Lower, Upper); 1112 } 1113 1114 RangeSet RangeConstraintManager::getSymLERange(ProgramStateRef St, 1115 SymbolRef Sym, 1116 const llvm::APSInt &Int, 1117 const llvm::APSInt &Adjustment) { 1118 return getSymLERange([&] { return getRange(St, Sym); }, Int, Adjustment); 1119 } 1120 1121 ProgramStateRef 1122 RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, 1123 const llvm::APSInt &Int, 1124 const llvm::APSInt &Adjustment) { 1125 RangeSet New = getSymLERange(St, Sym, Int, Adjustment); 1126 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 1127 } 1128 1129 ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange( 1130 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 1131 const llvm::APSInt &To, const llvm::APSInt &Adjustment) { 1132 RangeSet New = getSymGERange(State, Sym, From, Adjustment); 1133 if (New.isEmpty()) 1134 return nullptr; 1135 RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment); 1136 return Out.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, Out); 1137 } 1138 1139 ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange( 1140 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 1141 const llvm::APSInt &To, const llvm::APSInt &Adjustment) { 1142 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment); 1143 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment); 1144 RangeSet New(RangeLT.addRange(F, RangeGT)); 1145 return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New); 1146 } 1147 1148 //===----------------------------------------------------------------------===// 1149 // Pretty-printing. 1150 //===----------------------------------------------------------------------===// 1151 1152 void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State, 1153 const char *NL, unsigned int Space, 1154 bool IsDot) const { 1155 ConstraintRangeTy Constraints = State->get<ConstraintRange>(); 1156 1157 Indent(Out, Space, IsDot) << "\"constraints\": "; 1158 if (Constraints.isEmpty()) { 1159 Out << "null," << NL; 1160 return; 1161 } 1162 1163 ++Space; 1164 Out << '[' << NL; 1165 for (ConstraintRangeTy::iterator I = Constraints.begin(); 1166 I != Constraints.end(); ++I) { 1167 Indent(Out, Space, IsDot) 1168 << "{ \"symbol\": \"" << I.getKey() << "\", \"range\": \""; 1169 I.getData().print(Out); 1170 Out << "\" }"; 1171 1172 if (std::next(I) != Constraints.end()) 1173 Out << ','; 1174 Out << NL; 1175 } 1176 1177 --Space; 1178 Indent(Out, Space, IsDot) << "]," << NL; 1179 } 1180