connglli / ELEGANT

ELEGANT - a tool to Effectively LocatE fraGmentAtion-iNduced compaTibility issues.
MIT License
3 stars 0 forks source link

weekly report: 2017.12.06-2017.12.12 #11

Closed connglli closed 6 years ago

connglli commented 6 years ago

周报

2017.12.06 ~ 2017.12.12

上周的时候提了两个问题,并给出了(暂定的)解决方案,这周对其进行了实现。这里将对这两个问题给出更详细的步骤,并对代码进行部分解释。

computeCallsite 寻找不充分导致误报率提高

上周简单提到,对这个问题的解决欲采用 indirect-caller 的方式进行解决。采用这种方式,我们容易想到,对于某个 api A,它将有 n0 个 0-indirect-caller,而在每个 0-indirect-caller 内部,将有 n0i 个真正的 callsite(即真正的调用点),并且对于每个 0-indirect-caller,将有 n1i 个 1-indirect-caller... 如此所有 call sites 将形成一棵调用树。如图所示:


nsh


有了上面的 call sites tree 后,我们寻找可能存在的 FIC issues 过程就变成了下面的 3 步:

  1. 生成。即由 call graph 生成上面的图示。算法描述中将找到所有的 indirect-caller,但实际实现中考虑到现实以及性能我们使用 K-indirect-caller。
  2. 剪枝。很容易想到,在开发者未做任何 FIC issues 的 fix 情况下,上面所有由叶子节点到根节点的调用链都是一条会产生 FIC issue 的调用。因此我们需要将上面的树进行剪枝,删掉其中开发者已经解决掉的节点:对于所有的 call site 进行遍历,删除所有已经删除的 call sites,如果某个节点内部的 call sites 全部被 fix,那么直接删除该结点(及其子节点)。
  3. 路径生成。即 issue 触发。

重新描述一下算法过程:

algorighm do
  foreach api-context model ac in api-context model list do
    if (model does not satisfy FIC conditions)
      continue
    fi

    callSitesTree = create_Tree(callgraph, model.api) # creation
    callSitesTree = prune_Tree(callSitesTree, model)  # pruning
    issues = genPathes_Tree(callSitesTree, model)     # generating

    emit all issues
  done
done

function create_Tree(callgraph, api) do
  root = new Root({ caller: api })

  clarify all callsites of api by every callsite's method
  add all methods to root as root.method

  foreach method m in root.methods do
    childnode = create_Tree(callgraph, m)
    append childnode to root as a child node
  done
done

function prune_Tree(t) do
  queue = Queue(t.root)

  # we use BFS to traverse the tree
  while queue is not empty do
    node = queue.deque()
    foreach child node c in node.getChildren() do
      queue.enque(c)
    done

    foreach call site cs in node.getCallSites() do
      slicing = runBackgroundSlicing(cs)
      foreach slice s in slicing do
        if (s can fix issue) then
          delete cs in node
          break
        fi
      done
    done

    if node.getCallSites() == empty then
      while node.getParent() != t.root do
        node = node.getParent()
      done
      delete node in t
    fi
  done
done

function genPathes_Tree(t) do
    pathes = []

    foreach child node n in t.getChlidren do
      genPathes_Tree(n)
        .map(p, pathes.add(p.clone().append(t.caller)))
    done

    return pathes
done

代码实现位于 corecomputeCallSitesTreepruneCallSitesTree

修改 canHandleIssue 以提高精确度

上周已经详细说明了提高精确度的方式,这里不再赘述。这部分关于 Callsite 和 IfStmt 的实现已经基本完成,并且能对我们上次提到的情况进行分析并正确输出(下面的输出中 PATH of method calling 是会引起 FIC issue 的一条调用链,以这样的方式呈现,应该能给开发者更多的信息):

INVALID use of API: <android.app.Activity: android.app.ActionBar getActionBar()>
  PATH of method calling: [
    <com.example.fictest.MainActivity: void virtualCheck()>(~:58) ->
    <com.example.fictest.MainActivity: void _acpair_check_getActionBar()>(~:62) ->
    <android.app.Activity: android.app.ActionBar getActionBar()>
  ]
  SHOULD be used within the context:
     android API level:  [ 11, ~ ]
     android OS version: [ 1.0, ~ ]
     except:             [  ]
  Please check your api version or devices

INVALID use of API: <android.app.Activity: android.app.ActionBar getActionBar()>
  PATH of method calling: [
    <com.example.fictest.MainActivity: void virtualCheck()>(~:58) ->
    <com.example.fictest.MainActivity: void _acpair_check_getActionBar()>(~:65) ->
    <android.app.Activity: android.app.ActionBar getActionBar()>
  ]
  SHOULD be used within the context:
     android API level:  [ 11, ~ ]
     android OS version: [ 1.0, ~ ]
     except:             [  ]
  Please check your api version or devices

INVALID use of API: <android.app.Activity: android.app.ActionBar getActionBar()>
  PATH of method calling: [
    <com.example.fictest.MainActivity: void dontCheck()>(~:31) ->
    <com.example.fictest.MainActivity: void _acpair_check_getActionBar()>(~:62) ->
    <android.app.Activity: android.app.ActionBar getActionBar()>
  ]
  SHOULD be used within the context:
     android API level:  [ 11, ~ ]
     android OS version: [ 1.0, ~ ]
     except:             [  ]
  Please check your api version or devices

INVALID use of API: <android.app.Activity: android.app.ActionBar getActionBar()>
  PATH of method calling: [
    <com.example.fictest.MainActivity: void dontCheck()>(~:31) ->
    <com.example.fictest.MainActivity: void _acpair_check_getActionBar()>(~:65) ->
    <android.app.Activity: android.app.ActionBar getActionBar()>
  ]
  SHOULD be used within the context:
     android API level:  [ 11, ~ ]
     android OS version: [ 1.0, ~ ]
     except:             [  ]
  Please check your api version or devices

测试代码是:

public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dontCheck();
        directCheck();
        functionalCheck();
        interfCheck();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

    private void dontCheck() {
        _acpair_check_getActionBar();
    }

    private void directCheck() {
        if (Build.VERSION.SDK_INT > 11) {
            _acpair_check_getActionBar();
        }
    }

    private boolean isCompatible(int v) {
        return Build.VERSION.SDK_INT > v;
    }

    private void functionalCheck() {
        if (isCompatible((11))) {
            _acpair_check_getActionBar();
        }
    }

    private void interfCheck() {
        if (Compatiblity.isCompatible(11)) {
            _acpair_check_getActionBar();
        }
    }

    @Override
    protected void virtualCheck() {
        _acpair_check_getActionBar();
    }

    private void _acpair_check_getActionBar() {
        ActionBar actionBar = getActionBar();
        actionBar.setTitle("123");

        ActionBar secondActionBar = getActionBar();
        secondActionBar.setTitle("123");
    }

}

代码在 call-site-tree 分支。

关于 Value,发现了几点问题,现在还在考虑解决中。