mfbt/Poison.h
author Morten Stenshorne <mstensho@chromium.org>
Tue, 09 Oct 2018 04:14:13 +0000
changeset 495959 13844f50ee32e17f513b7c1013c2348200e21b8c
parent 476043 14f7dab3a9bd909e8ba5a9b05127f58e31139e63
child 505383 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1496274 [wpt PR 13345] - [LayoutNG] Correct clip-path reference box calculation., a=testonly Automatic update from web-platform-tests[LayoutNG] Correct clip-path reference box calculation. We used coordinates relatively to the line box, while we were expected by the caller to be relative to the containing block. Flipping for writing mode was bogus for NG (but needed by legacy), since NG uses truly physical coordinates. Hardened tests to contain a leading line and padding, and leading content on the first line of the clipped child. Bug: 641907 Change-Id: I2b1b9ff4ea92a6405fcdffcf139842458b46442f Cq-Include-Trybots: luci.chromium.try​:linux_layout_tests_layout_ng Reviewed-on: https://chromium-review.googlesource.com/c/1257913 Reviewed-by: Koji Ishii <kojii@chromium.org> Reviewed-by: Fredrik Söderquist <fs@opera.com> Commit-Queue: Morten Stenshorne <mstensho@chromium.org> Cr-Commit-Position: refs/heads/master@{#596554} -- wpt-commits: e9a0828c85819340f721f121aac19ab8eefa3439 wpt-pr: 13345

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * A poison value that can be used to fill a memory space with
 * an address that leads to a safe crash when dereferenced.
 */

#ifndef mozilla_Poison_h
#define mozilla_Poison_h

#include "mozilla/Assertions.h"
#include "mozilla/Types.h"

#include <stdint.h>
#include <string.h>

MOZ_BEGIN_EXTERN_C

extern MFBT_DATA uintptr_t gMozillaPoisonValue;

/**
 * @return the poison value.
 */
inline uintptr_t mozPoisonValue()
{
  return gMozillaPoisonValue;
}

/**
 * Overwrite the memory block of aSize bytes at aPtr with the poison value.
 * aPtr MUST be aligned at a sizeof(uintptr_t) boundary.
 * Only an even number of sizeof(uintptr_t) bytes are overwritten, the last
 * few bytes (if any) is not overwritten.
 */
inline void mozWritePoison(void* aPtr, size_t aSize)
{
  const uintptr_t POISON = mozPoisonValue();
  char* p = (char*)aPtr;
  char* limit = p + (aSize & ~(sizeof(uintptr_t) - 1));
  MOZ_ASSERT(aSize >= sizeof(uintptr_t), "poisoning this object has no effect");
  for (; p < limit; p += sizeof(uintptr_t)) {
    memcpy(p, &POISON, sizeof(POISON));
  }
}

/**
 * Initialize the poison value.
 * This should only be called once.
 */
extern MFBT_API void mozPoisonValueInit();

/* Values annotated by CrashReporter */
extern MFBT_DATA uintptr_t gMozillaPoisonBase;
extern MFBT_DATA uintptr_t gMozillaPoisonSize;

MOZ_END_EXTERN_C

#if defined(__cplusplus)

namespace mozilla {

/**
 * A version of CorruptionCanary that is suitable as a member of objects that
 * are statically allocated.
 */
class CorruptionCanaryForStatics {
public:
  constexpr CorruptionCanaryForStatics()
    : mValue(kCanarySet)
  {
  }

  // This is required to avoid static constructor bloat.
  ~CorruptionCanaryForStatics() = default;

  void Check() const {
    if (mValue != kCanarySet) {
      MOZ_CRASH("Canary check failed, check lifetime");
    }
  }

protected:
  uintptr_t mValue;

private:
  static const uintptr_t kCanarySet = 0x0f0b0f0b;
};


/**
 * This class is designed to cause crashes when various kinds of memory
 * corruption are observed. For instance, let's say we have a class C where we
 * suspect out-of-bounds writes to some members.  We can insert a member of type
 * Poison near the members we suspect are being corrupted by out-of-bounds
 * writes.  Or perhaps we have a class K we suspect is subject to use-after-free
 * violations, in which case it doesn't particularly matter where in the class
 * we add the member of type Poison.
 *
 * In either case, we then insert calls to Check() throughout the code.  Doing
 * so enables us to narrow down the location where the corruption is occurring.
 * A pleasant side-effect of these additional Check() calls is that crash
 * signatures may become more regular, as crashes will ideally occur
 * consolidated at the point of a Check(), rather than scattered about at
 * various uses of the corrupted memory.
 */
class CorruptionCanary : public CorruptionCanaryForStatics {
public:
  constexpr CorruptionCanary() = default;

  ~CorruptionCanary() {
    Check();
    mValue = mozPoisonValue();
  }
};

} // mozilla

#endif

#endif /* mozilla_Poison_h */