Commit 97c742e6 authored by Sajjad Mirza's avatar Sajjad Mirza
Browse files

[llvm-cov] Fix illegal cast from uint64_t to int64_t

Summary:
Counters are stored as uint64_t in the coverage mapping, but
exporting in JSON requires signed integers. Clamp the values to the
smaller range to make the conversion safe.

Reviewers: Dor1s, vsk

Reviewed By: Dor1s

Subscribers: llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D70200
parent 2c7c528d
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
#include <algorithm>
#include <limits>
#include <mutex>
#include <utility>

@@ -61,14 +62,23 @@ using namespace llvm;

namespace {

// The JSON library accepts int64_t, but profiling counts are stored as uint64_t.
// Therefore we need to explicitly convert from unsigned to signed, since a naive
// cast is implementation-defined behavior when the unsigned value cannot be
// represented as a signed value. We choose to clamp the values to preserve the
// invariant that counts are always >= 0.
int64_t clamp_uint64_to_int64(uint64_t u) {
  return std::min(u, static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
}

json::Array renderSegment(const coverage::CoverageSegment &Segment) {
  return json::Array({Segment.Line, Segment.Col, int64_t(Segment.Count),
  return json::Array({Segment.Line, Segment.Col, clamp_uint64_to_int64(Segment.Count),
                      Segment.HasCount, Segment.IsRegionEntry});
}

json::Array renderRegion(const coverage::CountedRegion &Region) {
  return json::Array({Region.LineStart, Region.ColumnStart, Region.LineEnd,
                      Region.ColumnEnd, int64_t(Region.ExecutionCount),
                      Region.ColumnEnd, clamp_uint64_to_int64(Region.ExecutionCount),
                      Region.FileID, Region.ExpandedFileID,
                      int64_t(Region.Kind)});
}
@@ -182,7 +192,7 @@ json::Array renderFunctions(
  for (const auto &F : Functions)
    FunctionArray.push_back(
        json::Object({{"name", F.Name},
                      {"count", int64_t(F.ExecutionCount)},
                      {"count", clamp_uint64_to_int64(F.ExecutionCount)},
                      {"regions", renderRegions(F.CountedRegions)},
                      {"filenames", json::Array(F.Filenames)}}));
  return FunctionArray;