[PATCH] D34430: [Clang][TypoCorrection] Clang hangs in typo correction

Oleg Ranevskyy via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 20 17:00:45 PDT 2017

iid_iunknown created this revision.
iid_iunknown added a project: clang.

This is a patch for PR33484.
The clang's typo correction logic may fall into an infinite loop when reaching the typo correction limit.

When some complex expression has multiple typos in it, clang finds possible corrections for each typo and processes various permutations of these corrections. The typo corrections counter is incremented during the process and compared to the max allowed limit (50 by default). Hang may happen if the limit is reached in the middle of complex expression processing. In this case transform of the current part of the expression fails, making clang ignore its subsequent parts and bail out to the main transform loop in `TransformTypos::Transform(Expr *E)`. On the next iteration, clang fails at the very beginning of transform and no longer reaches the rest of the expression immediately bailing out to the main loop. The transform cannot advance since this moment. As the loop exit condition requires either a fully successful transform or having all the permutations processed, it can never become true.

Yet another reproducer with a readable C++ code:

    struct V
      float x;
    class H
      const V& getV() const { return mV; }
      int getN() const { return mN; }
      V mV;
      int mN;
    class T
      const H& getH0() const { return mH0; }
      const H& getH1() const { return mH1; }
      const V& getV0() const { return mH0.getV(); }
      const V& getV1() const { return mH1.getV(); }
      H mH0;
      H mH1;
    T sT;
    H sH;
  void func()
    ( sT.getH2().getM() > sH.getM() ?
      sT.getH3() :
      0 );

Here, both the condition and LHS of `?:` have typos. If the limit is exceeded, the transform will fail on the condition and will no longer proceed to LHS and process its substitutions.

The patch adds a limit check into the main loop exit condition.




Index: lib/Sema/SemaExprCXX.cpp
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -7246,10 +7246,13 @@
   /// TransformCache). Returns true if there is still any untried combinations
   /// of corrections.
   bool CheckAndAdvanceTypoExprCorrectionStreams() {
+	bool CheckLimitExceeded =
+        SemaRef.TyposCorrected >=
+        SemaRef.getDiagnostics().getDiagnosticOptions().SpellCheckingLimit;
     for (auto TE : TypoExprs) {
       auto &State = SemaRef.getTypoExprState(TE);
-      if (!State.Consumer->finished())
+	  if (!CheckLimitExceeded && !State.Consumer->finished())
         return true;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D34430.103289.patch
Type: text/x-patch
Size: 786 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170621/47a0435e/attachment.bin>

More information about the cfe-commits mailing list