/* Support for scanning buffers for a NUL terminator (for C-style strings).
   Copyright (C) 2019-2026 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "analyzer/common.h"

#include "fold-const.h"
#include "tree-diagnostic.h"
#include "tm.h"

#include "selftest.h"

#include "analyzer/symbolic-bit-vectors.h"
#include "analyzer/region-model.h"
#include "analyzer/string-scan.h"
#include "analyzer/analyzer-selftests.h"

#if ENABLE_ANALYZER

namespace ana {

void
string_scan::dump_to_pp (pretty_printer *pp) const
{
  pp_string (pp, "string_scan::");
  pp_string (pp, state_to_string (m_state));
  pp_string (pp, "(");
  m_byte_offset.dump_to_pp (pp);
  pp_string (pp, "_bytes");
  if (m_state == state::found_poison)
    pp_printf (pp, ", %s", poison_kind_to_str (m_poison_kind));
  pp_string (pp, ")");
}

DEBUG_FUNCTION void
string_scan::dump () const
{
  tree_dump_pretty_printer pp (stderr);
  dump_to_pp (&pp);
  pp_newline (&pp);
}

const char *
string_scan::state_to_string (enum state s)
{
  switch (s)
    {
    default:
      gcc_unreachable ();

    case state::found_nul:
      return "found_nul";

    case state::found_poison:
      return "found_poison";

    case state::beyond_domain:
      return "beyond_domain";

    case state::cannot_scan:
      return "cannot_scan";
    }
}

namespace symbolic {

static string_scan
scan_string_cst_for_null_terminator (tree string_cst,
				     concrete_byte_offset start_byte_offset)
{
  gcc_assert (TREE_CODE (string_cst) == STRING_CST);

  tree cst_size = get_string_cst_size (string_cst);
  if (!cst_size)
    return string_scan::cannot_scan (start_byte_offset);
  if (TREE_CODE (cst_size) != INTEGER_CST)
    return string_scan::cannot_scan (start_byte_offset);

  auto string_len
    = integer_with_unit<units::byte> (TREE_STRING_LENGTH (string_cst));
  /* Assume all bytes after TREE_STRING_LENGTH are zero.  This handles
     the case where an array is initialized with a string_cst that isn't
     as long as the array, where the remaining elements are
     empty-initialized and thus zeroed.  */
  if (start_byte_offset >= string_len)
    return string_scan::found_nul (start_byte_offset);

  /* Look for the first 0 byte within STRING_CST
     from START_READ_OFFSET onwards.  */
  const char *start = (TREE_STRING_POINTER (string_cst)
		       + start_byte_offset.as_unsigned_long ());
  size_t remaining_bytes
    = TREE_STRING_LENGTH (string_cst) - start_byte_offset.as_unsigned_long ();
  if (const void *p = memchr (start, 0, remaining_bytes))
    {
      /* Found NUL.  */
      return string_scan::found_nul
	(concrete_byte_offset ((const char *)p
			       - TREE_STRING_POINTER (string_cst)));
    }
  else
    {
      /* Didn't find NUL.  */
      return string_scan::beyond_domain (string_len);
    }
}

static string_scan
scan_raw_data_cst_for_null_terminator (tree raw_data_cst,
				       concrete_byte_offset start_byte_offset)
{
  gcc_assert (TREE_CODE (raw_data_cst) == RAW_DATA_CST);
  gcc_assert (start_byte_offset >= 0_bytes);
  gcc_assert (start_byte_offset
	      < concrete_byte_offset (RAW_DATA_LENGTH (raw_data_cst)));

  const unsigned char *start
    = &RAW_DATA_UCHAR_ELT (raw_data_cst, start_byte_offset.as_unsigned_long ());
  size_t remaining_bytes
    = RAW_DATA_LENGTH (raw_data_cst) - start_byte_offset.as_unsigned_long ();
  if (const void *p = memchr (start, 0, remaining_bytes))
    {
      /* Found NUL.  */
      return string_scan::found_nul
	(concrete_byte_offset ((const unsigned char *)p
			       - &RAW_DATA_UCHAR_ELT (raw_data_cst, 0)));
    }
  else
    {
      /* Didn't find NUL.  */
      return string_scan::beyond_domain
	(concrete_byte_offset (RAW_DATA_LENGTH (raw_data_cst)));
    }
}

static string_scan
scan_tree_cst_for_null_terminator (tree tree_cst,
				   concrete_bit_size size_in_bits,
				   concrete_byte_offset start_byte_offset)
{
  gcc_assert (start_byte_offset >= 0_bytes);

  switch (TREE_CODE (tree_cst))
    {
    default:
      gcc_unreachable ();

    case COMPLEX_CST:
    case VECTOR_CST:
    case INTEGER_CST:
      if (size_in_bits == concrete_bit_size (BITS_PER_UNIT))
	{
	  /* We have a one-byte constant.
	     It's either a zero byte or a non-zero byte.  */
	  gcc_assert (start_byte_offset == 0_bytes);
	  if (zerop (tree_cst))
	    return string_scan::found_nul (0_bytes);
	  else
	    return string_scan::beyond_domain (1_byte);
	}
      else
	{
	  // sizeof > 1:
	  if (zerop (tree_cst))
	    return string_scan::found_nul (0_bytes);
	  else
	    {
	      /* Use native_encode_expr and extract the pertinent byte(s).  */
	      unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT];
	      int size = native_encode_expr (tree_cst, buf, sizeof buf, 0);
	      if (size == 0)
		string_scan::cannot_scan (start_byte_offset);
	      if (start_byte_offset < 0_bytes)
		return string_scan::cannot_scan (start_byte_offset);
	      if (start_byte_offset >= concrete_byte_size (size))
		return string_scan::beyond_domain (start_byte_offset);
	      for (int offset = start_byte_offset.as_unsigned_long ();
		   offset < size; ++offset)
		if (buf[offset] == '\0')
		  return string_scan::found_nul (concrete_byte_offset (offset));
	      return string_scan::beyond_domain (concrete_byte_offset (size));
	    }
	}
      break;

    case STRING_CST:
      return scan_string_cst_for_null_terminator (tree_cst,
						  start_byte_offset);

    case RAW_DATA_CST:
      return scan_raw_data_cst_for_null_terminator (tree_cst,
						    start_byte_offset);
    }

  return string_scan::cannot_scan (start_byte_offset);
}

string_scan
concat_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset byte_offset) const
{
  concrete_byte_offset byte_offset_relative_to_iter = byte_offset;
  concrete_byte_offset accum_byte_sizes = 0_bytes;
  for (auto iter : m_bit_vectors)
    {
      concrete_byte_size iter_byte_size;
      if (!iter->maybe_get_concrete_size_in_bytes (&iter_byte_size))
	return string_scan::cannot_scan (byte_offset);
      if (byte_offset_relative_to_iter < iter_byte_size)
	{
	  auto nested_scan
	    = iter->scan_for_first_zero_byte (byte_offset_relative_to_iter);
	  if (nested_scan.m_state != string_scan::state::beyond_domain)
	    return string_scan (accum_byte_sizes + nested_scan.m_byte_offset,
				nested_scan.m_state);
	}
      else
	{
	  /* "iter" is a leading element fully before the initial byte offset:
	     skip it altogether.  */
	}
      accum_byte_sizes += iter_byte_size;
      byte_offset_relative_to_iter -= iter_byte_size;
      if (byte_offset_relative_to_iter < 0_bytes)
	byte_offset_relative_to_iter = 0_bytes;
    }
  return string_scan::beyond_domain (accum_byte_sizes);
}

string_scan
conjured_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset byte_offset) const
{
  return string_scan::cannot_scan (byte_offset);
}

string_scan
cropped_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  concrete_bit_range uncropped_bits_to_use;
  if (!concrete_from_symbolic (get_uncropped_bits_to_use (),
			       &uncropped_bits_to_use))
    return string_scan::cannot_scan (start_byte_offset);
  concrete_byte_range uncropped_bytes_to_use;
  if (!maybe_bytes_from_bits (uncropped_bits_to_use,
			      &uncropped_bytes_to_use))
    return string_scan::cannot_scan (start_byte_offset);

  /* Scan the uncropped bit_vector, starting at START_BYTE_OFFSET
     adjusted relative to the beginning of the cropping.  */
  string_scan nested_scan
    = m_uncropped_bv.scan_for_first_zero_byte
    (uncropped_bytes_to_use.get_start_offset () + start_byte_offset);

  /* If the first thing that happened in the nested scan was beyond the
     cropped region, then simply advance the outer scan to the end of
     the cropped region.  */
  if (nested_scan.m_byte_offset >= uncropped_bytes_to_use.get_next_offset ())
    return string_scan::beyond_domain
      (std::max (start_byte_offset,
		 uncropped_bytes_to_use.get_size ()));

  /* Otherwise, report the location of interest relative to the start
     of this cropped bit_vector.  */
  return string_scan (nested_scan.m_byte_offset
		      - uncropped_bytes_to_use.get_start_offset (),
		      nested_scan.m_state);
}

#if CHECKING_P

string_scan
named_test_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  return string_scan::cannot_scan (start_byte_offset);
}

#endif /* #if CHECKING_P */

string_scan
empty_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset byte_offset) const
{
  return string_scan::beyond_domain (byte_offset);
}

string_scan
poisoned_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  return string_scan::cannot_scan (start_byte_offset);
}

/* Scan for null terminator within repeated bit_vector.
    . +-----+-----+-----+-----+-----+-----+
    . |     |     |     |     |     |     |
    . +-----+-----+-----+-----+-----+-----+
    .                ^
    .                start_byte_offset
   Do a partial scan within the first repetition we're at;
   failing that, try the next (if any).  */

string_scan
repeated_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  concrete_byte_size inner_byte_size;
  if (!m_inner_bv.maybe_get_concrete_size_in_bytes (&inner_byte_size))
    return string_scan::cannot_scan (start_byte_offset);

  concrete_integer conc_repeat_count;
  if (!concrete_from_symbolic (m_repeat_count, &conc_repeat_count))
    return string_scan::cannot_scan (start_byte_offset);

  /* If we're starting within a repetition, perform a partial scan of the
     repetition of the inner bit_vector that we hit at START_BYTE_OFFSET, e.g.:
    . +0----+1----+2----+3----+4----+5----+
    . |     |     |     |     |     |     |
    . +-----+-----+-----+-----+-----+-----+
    .                ^
    .                start_byte_offset
    .                V
    .             +-----+
    .             |     |
    .             +-----+
  */
  concrete_byte_offset byte_offset_within_initial
    = (start_byte_offset.floor_mod (inner_byte_size));
  if (byte_offset_within_initial > 0_bytes)
    {
      auto partial_instance_index
	= start_byte_offset.floor_div (inner_byte_size);
      const string_scan partial_nested_scan
	= m_inner_bv.scan_for_first_zero_byte (byte_offset_within_initial);
      if (partial_nested_scan.m_state != string_scan::state::beyond_domain)
	{
	  concrete_byte_offset start_byte_offset_of_partial_instance
	    = partial_instance_index * inner_byte_size;
	  return string_scan ((start_byte_offset_of_partial_instance
			       + partial_nested_scan.m_byte_offset),
			      partial_nested_scan.m_state);
	}
    }

  /* Otherwise, we haven't found anything yet; look from the start of
     the next full repetition of the inner bit_vector, if there is one.
    . +0----+1----+2----+3----+4----+5----+
    . |     |     |     |     |     |     |
    . +-----+-----+-----+-----+-----+-----+
    .                   ^
    .                   V
    .                   +-----+
    .                   |     |
    .                   +-----+

  */
  auto full_instance_index = start_byte_offset.floor_div (inner_byte_size);
  if (full_instance_index < conc_repeat_count)
    {
      const string_scan full_nested_scan
	= m_inner_bv.scan_for_first_zero_byte (0_bytes);
      if (full_nested_scan.m_state != string_scan::state::beyond_domain)
	{
	  concrete_byte_offset start_byte_offset_of_full_instance
	    = (full_instance_index * inner_byte_size);
	  return string_scan ((start_byte_offset_of_full_instance
			       + full_nested_scan.m_byte_offset),
			      full_nested_scan.m_state);
	}
    }

  /* Otherwise, we've run out of repetitions.  */
  return string_scan::beyond_domain (inner_byte_size * conc_repeat_count);
}

string_scan
bit_vector_from_svalue::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  switch (m_sval.get_kind ())
    {
    default:
      break;

    case SK_CONSTANT:
      {
	concrete_bit_size conc_size;
	if (!concrete_from_symbolic (get_size (), &conc_size))
	  gcc_unreachable ();
	tree cst = as_a<const constant_svalue *> (&m_sval)->get_constant ();
	return scan_tree_cst_for_null_terminator (cst,
						  conc_size,
						  start_byte_offset);
      }

    case SK_INITIAL:
      {
	auto *initial_sval = as_a<const initial_svalue *> (&m_sval);
	auto &reg = *initial_sval->get_region ();
	switch (reg.get_kind ())
	  {
	  default:
	    break;

	  case RK_STRING:
	    {
	      auto *string_reg = as_a<const string_region *> (&reg);
	      return scan_string_cst_for_null_terminator
		(string_reg->get_string_cst (),
		 start_byte_offset);
	    }
	  }
      }
      break;
    }

  return string_scan::cannot_scan (start_byte_offset);
}

string_scan
bit_vector_from_ubc::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  return string_scan::cannot_scan (start_byte_offset);
}

string_scan
tristate_bit_vector::
scan_for_first_zero_byte (concrete_byte_offset start_byte_offset) const
{
  concrete_byte_size size_in_bytes;
  if (!maybe_get_concrete_size_in_bytes (&size_in_bytes))
    return string_scan::cannot_scan (start_byte_offset);

  gcc_assert (size_in_bytes >= start_byte_offset);

  switch (m_bit_value.get_value ())
    {
    default:
      gcc_unreachable ();

    case tristate::TS_UNKNOWN:
      return string_scan::cannot_scan (start_byte_offset);

    case tristate::TS_TRUE:
      // All ones: NUL not found.
      return string_scan::beyond_domain (size_in_bytes);

    case tristate::TS_FALSE:
      // All zeros: NUL immediately found.
      return string_scan::found_nul (start_byte_offset);
    }
}

} // namespace ana::symbolic

#if CHECKING_P

namespace selftest {

static void
test_string_scan_dump ()
{
  {
    pretty_printer pp;
    string_scan::found_nul (5_bytes).dump_to_pp (&pp);
    ASSERT_STREQ (pp_formatted_text (&pp),
		  "string_scan::found_nul(5_bytes)");
  }
  {
    pretty_printer pp;
    string_scan::found_poison (100_bytes, poison_kind::uninit).dump_to_pp (&pp);
    ASSERT_STREQ (pp_formatted_text (&pp),
		  "string_scan::found_poison(100_bytes, uninit)");
  }
  {
    pretty_printer pp;
    string_scan::beyond_domain (1024_bytes).dump_to_pp (&pp);
    ASSERT_STREQ (pp_formatted_text (&pp),
		  "string_scan::beyond_domain(1024_bytes)");
  }
  {
    pretty_printer pp;
    string_scan::cannot_scan (42_bytes).dump_to_pp (&pp);
    ASSERT_STREQ (pp_formatted_text (&pp),
		  "string_scan::cannot_scan(42_bytes)");
  }
}

// Test scanning a string constant for NUL.

static void
test_scan_string_constant ()
{
  tree string_cst_ptr = make_string_constant ("abc");

  symbolic::node_manager node_mgr;
  auto &mgr = node_mgr.get_bit_vector_manager ();

  auto &abc0 = mgr.get_bits_for_constant (string_cst_ptr);

  for (concrete_byte_offset i = 0_bytes; i < 4_bytes; ++i)
    ASSERT_EQ (abc0.scan_for_first_zero_byte (i),
	       string_scan::found_nul (3_bytes));
}

static void
test_scan_integer_constants ()
{
  symbolic::node_manager node_mgr;
  auto &mgr = node_mgr.get_bit_vector_manager ();

  /* sizeof() > 1, all zero: NUL at byte 0.  */
  {
    auto &int_0
      = mgr.get_bits_for_constant (build_int_cst (integer_type_node, 0));
    ASSERT_EQ (int_0.scan_for_first_zero_byte (0_bytes),
	       string_scan::found_nul (0_bytes));
  }

  /* sizeof() > 1, not all zero.  */
  {
    auto &int_42
      = mgr.get_bits_for_constant (build_int_cst (uint32_type_node, 42));
    if (BYTES_BIG_ENDIAN)
      {
	/* Big-endian.  */
	/* First 3 bytes are all zero.  */
	for (auto i = 0_bytes; i < 3_bytes; ++i)
	  ASSERT_EQ (int_42.scan_for_first_zero_byte (i),
		     string_scan::found_nul (i));
	/* Then non-zero.  */
	ASSERT_EQ (int_42.scan_for_first_zero_byte (3_bytes),
		   string_scan::beyond_domain (4_bytes));
      }
    else
      {
	/* Little-endian.  */
	if (!WORDS_BIG_ENDIAN)
	  {
	    /* First byte is non-zero (42).  */
	    ASSERT_EQ (int_42.scan_for_first_zero_byte (0_bytes),
		       string_scan::found_nul (1_byte));
	    /* Then 3 zero bytes.  */
	    for (auto i = 1_byte; i < 4_bytes; ++i)
	      ASSERT_EQ (int_42.scan_for_first_zero_byte (i),
			 string_scan::found_nul (i));
	  }
      }
  }

  /* sizeof() == 1.  */
  auto &char_00
    = mgr.get_bits_for_constant (build_int_cst (char_type_node, 0));
  ASSERT_EQ (char_00.scan_for_first_zero_byte (0_bytes),
	     string_scan::found_nul (0_bytes));

  auto &char_a
    = mgr.get_bits_for_constant (build_int_cst (char_type_node, 'a'));
  ASSERT_EQ (char_a.scan_for_first_zero_byte (0_bytes),
	     string_scan::beyond_domain (1_byte));

  auto &char_b
    = mgr.get_bits_for_constant (build_int_cst (char_type_node, 'b'));
  ASSERT_EQ (char_b.scan_for_first_zero_byte (0_bytes),
	     string_scan::beyond_domain (1_byte));
}

static void
test_scan_tristates ()
{
  symbolic::node_manager node_mgr;
  auto &mgr = node_mgr.get_bit_vector_manager ();

  {
    auto &byte_00 = mgr.get_all_zeros (1_byte);
    ASSERT_EQ (byte_00.scan_for_first_zero_byte (0_bytes),
	       string_scan::found_nul (0_bytes));
  }
  {
    auto &byte_ff = mgr.get_all_ones (1_byte);
    ASSERT_EQ (byte_ff.scan_for_first_zero_byte (0_bytes),
	       string_scan::beyond_domain (1_byte));
  }
  {
    auto &byte_unknown = mgr.get_tristate_bits (8_bits, tristate::unknown ());
    ASSERT_EQ (byte_unknown.scan_for_first_zero_byte (0_bytes),
	       string_scan::cannot_scan (0_bytes));
  }
}

/* Return true iff default_tree_printer prints "char" for
   %T with char_type_node.

   2026-11-05(dmalcolm): crab1 seems to print char_type_node as
   "unsigned char", whereas cc1 and cc1plus print it as "char".  */

static bool
char_type_node_printed_as_char_p ()
{
  pretty_printer pp;
  pp_format_decoder (&pp) = default_tree_printer;
  pp_printf (&pp, "%T", char_type_node);
  return strcmp (pp_formatted_text (&pp), "char") == 0;
}

static void
test_scan_concat ()
{
  symbolic::node_manager node_mgr;
  auto &mgr = node_mgr.get_bit_vector_manager ();

  auto &abc0 = mgr.get_bits_for_constant (make_string_constant ("abc"));
  auto &def0 = mgr.get_bits_for_constant (make_string_constant ("def"));

  {
    auto &abc0def0 = mgr.get_concat_bits ({&abc0, &def0});

    if (char_type_node_printed_as_char_p ())
      ASSERT_SYMBOLIC_NODE_DUMP_EQ
	(abc0def0,
	 ("concat_bit_vector[size: 8 bytes]\n"
	  "+- bit_vector_from_svalue[size: 4 bytes]\n"
	  "|  `- m_sval: 'const char[4]': constant_svalue ('\"abc\"')\n"
	  "`- bit_vector_from_svalue[size: 4 bytes]\n"
	  "   `- m_sval: 'const char[4]': constant_svalue ('\"def\"')\n"));

    for (concrete_byte_offset i = 0_bytes; i < 4_bytes; ++i)
      ASSERT_EQ (abc0def0.scan_for_first_zero_byte (i),
		 string_scan::found_nul (3_bytes));
    for (concrete_byte_offset i = 4_bytes; i < 8_bytes; ++i)
      ASSERT_EQ (abc0def0.scan_for_first_zero_byte (i),
		 string_scan::found_nul (7_bytes));
  }

  // Concat, cropping the terminator from "abc"
  {
    auto &abcdef0
      = mgr.get_concat_bits ({&abc0.get_cropped_bytes (concrete_byte_range (0_bytes, 3_bytes)),
			      &def0});

    if (char_type_node_printed_as_char_p ())
      ASSERT_SYMBOLIC_NODE_DUMP_EQ
	(abcdef0,
	 ("concat_bit_vector[size: 7 bytes]\n"
	  "+- cropped_bit_vector[size: 3 bytes]: [bytes 0..3)\n"
	  "|  `- uncropped: bit_vector_from_svalue[size: 4 bytes]\n"
	  "|     `- m_sval: 'const char[4]': constant_svalue ('\"abc\"')\n"
	  "`- bit_vector_from_svalue[size: 4 bytes]\n"
	  "   `- m_sval: 'const char[4]': constant_svalue ('\"def\"')\n"));

    for (concrete_byte_offset i = 0_bytes; i < 7_bytes; ++i)
      ASSERT_EQ (abcdef0.scan_for_first_zero_byte (i),
		 string_scan::found_nul (6_bytes));
  }
}

static void
test_scan_cropped ()
{
  symbolic::node_manager node_mgr;
  auto &mgr = node_mgr.get_bit_vector_manager ();

  auto &abc0 = mgr.get_bits_for_constant (make_string_constant ("abc"));

  // Crop the terminator from "abc"
  {
    auto &abc = abc0.get_cropped_bytes( concrete_byte_range (0_bytes, 3_bytes));
    for (concrete_byte_offset i = 0_bytes; i < 3_bytes; ++i)
      ASSERT_EQ (abc.scan_for_first_zero_byte (i),
		 string_scan::beyond_domain (3_bytes));
  }
}

static void
test_scan_repeated ()
{
  symbolic::node_manager node_mgr;
  auto &mgr = node_mgr.get_bit_vector_manager ();

  auto &char_a
    = mgr.get_bits_for_constant (build_int_cst (char_type_node, 'a'));
  auto &char_b
    = mgr.get_bits_for_constant (build_int_cst (char_type_node, 'b'));

  {
    auto &aaa = mgr.get_repeated_bits (char_a, 3);
    for (concrete_byte_offset i = 0_bytes; i < 3_bytes; ++i)
      ASSERT_EQ (aaa.scan_for_first_zero_byte (i),
		 string_scan::beyond_domain (3_bytes));
  }

  {
    auto &ab = mgr.get_concat_bits ({&char_a, &char_b});
    auto &ababab = mgr.get_repeated_bits (ab, 3);
    for (concrete_byte_offset i = 0_bytes; i < 6_bytes; ++i)
      ASSERT_EQ (ababab.scan_for_first_zero_byte (i),
		 string_scan::beyond_domain (6_bytes));
  }

  {
    tree string_cst_ptr = make_string_constant ("abc");
    auto &abc0 = mgr.get_bits_for_constant (string_cst_ptr);
    auto &abc0abc0abc0 = mgr.get_repeated_bits (abc0, 3);
    for (concrete_byte_offset i = 0_bytes; i < 4_bytes; ++i)
      ASSERT_EQ (abc0abc0abc0.scan_for_first_zero_byte (i),
		 string_scan::found_nul (3_bytes));
    for (concrete_byte_offset i = 4_bytes; i < 7_bytes; ++i)
      ASSERT_EQ (abc0abc0abc0.scan_for_first_zero_byte (i),
		 string_scan::found_nul (7_bytes));
    for (concrete_byte_offset i = 8_bytes; i < 12_bytes; ++i)
      ASSERT_EQ (abc0abc0abc0.scan_for_first_zero_byte (i),
		 string_scan::found_nul (11_bytes));
  }
}

/* Run all of the selftests within this file.  */

void
analyzer_string_scan_cc_tests ()
{
  test_string_scan_dump ();
  test_scan_string_constant ();
  test_scan_integer_constants ();
  test_scan_tristates ();
  test_scan_concat ();
  test_scan_cropped ();
  test_scan_repeated ();
}

} // namespace selftest

#endif /* CHECKING_P */

} // namespace ana

#endif /* #if ENABLE_ANALYZER */
