Ejemplo n.º 1
0
static void
randomly_set_extreme_ints (const DBusString *orig_data,
                           DBusString       *mutated)
{
  int i;
  int byte_order;
  const char *d;
  dbus_uint32_t orig;
  static int which = 0;
  unsigned int extreme_ints[] = {
    _DBUS_INT_MAX,
    _DBUS_UINT_MAX,
    _DBUS_INT_MAX - 1,
    _DBUS_UINT_MAX - 1,
    _DBUS_INT_MAX - 2,
    _DBUS_UINT_MAX - 2,
    _DBUS_INT_MAX - 17,
    _DBUS_UINT_MAX - 17,
    _DBUS_INT_MAX / 2,
    _DBUS_INT_MAX / 3,
    _DBUS_UINT_MAX / 2,
    _DBUS_UINT_MAX / 3,
    0, 1, 2, 3,
    (unsigned int) -1,
    (unsigned int) -2,
    (unsigned int) -3
  };
    
  if (orig_data != mutated)
    {
      _dbus_string_set_length (mutated, 0);
      
      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
        _dbus_assert_not_reached ("out of mem");
    }

  if (_dbus_string_get_length (mutated) < 12)
    return;
  
  d = _dbus_string_get_const_data (mutated);

  if (!(*d == DBUS_LITTLE_ENDIAN ||
        *d == DBUS_BIG_ENDIAN))
    return;

  byte_order = *d;
  
  i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
  i = _DBUS_ALIGN_VALUE (i, 4);

  orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);

  which = random_int_in_range (0, _DBUS_N_ELEMENTS (extreme_ints));

  _dbus_assert (which >= 0);
  _dbus_assert (which < _DBUS_N_ELEMENTS (extreme_ints));
  
  _dbus_marshal_set_uint32 (mutated, byte_order, i,
                            extreme_ints[which]);
}
static dbus_bool_t
create_unique_client_name (BusRegistry *registry,
                           DBusString  *str)
{
  /* We never want to use the same unique client name twice, because
   * we want to guarantee that if you send a message to a given unique
   * name, you always get the same application. So we use two numbers
   * for INT_MAX * INT_MAX combinations, should be pretty safe against
   * wraparound.
   */
  /* FIXME these should be in BusRegistry rather than static vars */
  static int next_major_number = 0;
  static int next_minor_number = 0;
  int len;
  
  len = _dbus_string_get_length (str);
  
  while (TRUE)
    {
      /* start out with 1-0, go to 1-1, 1-2, 1-3,
       * up to 1-MAXINT, then 2-0, 2-1, etc.
       */
      if (next_minor_number <= 0)
        {
          next_major_number += 1;
          next_minor_number = 0;
          if (next_major_number <= 0)
            _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
        }

      _dbus_assert (next_major_number > 0);
      _dbus_assert (next_minor_number >= 0);

      /* appname:MAJOR-MINOR */
      
      if (!_dbus_string_append (str, ":"))
        return FALSE;
      
      if (!_dbus_string_append_int (str, next_major_number))
        return FALSE;

      if (!_dbus_string_append (str, "."))
        return FALSE;
      
      if (!_dbus_string_append_int (str, next_minor_number))
        return FALSE;

      next_minor_number += 1;
      
      /* Check if a client with the name exists */
      if (bus_registry_lookup (registry, str) == NULL)
	break;

      /* drop the number again, try the next one. */
      _dbus_string_set_length (str, len);
    }

  return TRUE;
}
dbus_bool_t
_dbus_directory_get_next_file (DBusDirIter      *iter,
                               DBusString       *filename,
                               DBusError        *error)
{
  struct dirent *d, *ent;
  size_t buf_size;
  int err;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
  if (!dirent_buf_size (iter->d, &buf_size))
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "Can't calculate buffer size when reading directory");
      return FALSE;
    }

  d = (struct dirent *)dbus_malloc (buf_size);
  if (!d)
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
                      "No memory to read directory entry");
      return FALSE;
    }

 again:
  err = readdir_r (iter->d, d, &ent);
  if (err || !ent)
    {
      if (err != 0)
        dbus_set_error (error,
                        _dbus_error_from_errno (err),
                        "%s", _dbus_strerror (err));

      dbus_free (d);
      return FALSE;
    }
  else if (ent->d_name[0] == '.' &&
           (ent->d_name[1] == '\0' ||
            (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
    goto again;
  else
    {
      _dbus_string_set_length (filename, 0);
      if (!_dbus_string_append (filename, ent->d_name))
        {
          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
                          "No memory to read directory entry");
          dbus_free (d);
          return FALSE;
        }
      else
        {
          dbus_free (d);
          return TRUE;
        }
    }
}
Ejemplo n.º 4
0
static dbus_bool_t
find_next_typecode (DBusMessageDataIter *iter,
                    DBusString          *data,
                    DBusValidity        *expected_validity)
{
  int body_seq;
  int byte_seq;
  int base_depth;

  base_depth = iter->depth;

 restart:
  _dbus_assert (iter->depth == (base_depth + 0));
  _dbus_string_set_length (data, 0);

  body_seq = iter_get_sequence (iter);
  
  if (!generate_many_bodies (iter, data, expected_validity))
    return FALSE;
  /* Undo the "next" in generate_many_bodies */
  iter_set_sequence (iter, body_seq);
  
  iter_recurse (iter);
  while (TRUE)
    {
      _dbus_assert (iter->depth == (base_depth + 1));
      
      byte_seq = iter_get_sequence (iter);

      _dbus_assert (byte_seq <= _dbus_string_get_length (data));
      
      if (byte_seq == _dbus_string_get_length (data))
        {
          /* reset byte count */
          iter_set_sequence (iter, 0);
          iter_unrecurse (iter);
          _dbus_assert (iter->depth == (base_depth + 0));
          iter_next (iter); /* go to the next body */
          goto restart;
        }

      _dbus_assert (byte_seq < _dbus_string_get_length (data));

      if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
        break;
      else
        iter_next (iter);
    }

  _dbus_assert (byte_seq == iter_get_sequence (iter));
  _dbus_assert (byte_seq < _dbus_string_get_length (data));

  iter_unrecurse (iter);

  _dbus_assert (iter->depth == (base_depth + 0));
  
  return TRUE;
}
Ejemplo n.º 5
0
static dbus_bool_t
generate_typecode_changed (DBusMessageDataIter *iter,
                           DBusString          *data,
                           DBusValidity        *expected_validity)
{
  int byte_seq;
  int typecode_seq;
  int base_depth;

  base_depth = iter->depth;

 restart:
  _dbus_assert (iter->depth == (base_depth + 0));
  _dbus_string_set_length (data, 0);
  
  if (!find_next_typecode (iter, data, expected_validity))
    return FALSE;

  iter_recurse (iter);
  byte_seq = iter_get_sequence (iter);

  _dbus_assert (byte_seq < _dbus_string_get_length (data));
  
  iter_recurse (iter);
  typecode_seq = iter_get_sequence (iter);
  iter_next (iter);

  _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
  
  if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
    {
      _dbus_assert (iter->depth == (base_depth + 2));
      iter_set_sequence (iter, 0); /* reset typecode sequence */
      iter_unrecurse (iter);
      _dbus_assert (iter->depth == (base_depth + 1));
      iter_next (iter); /* go to the next byte_seq */
      iter_unrecurse (iter);
      _dbus_assert (iter->depth == (base_depth + 0));
      goto restart;
    }

  _dbus_assert (iter->depth == (base_depth + 2));
  iter_unrecurse (iter);
  _dbus_assert (iter->depth == (base_depth + 1));
  iter_unrecurse (iter);
  _dbus_assert (iter->depth == (base_depth + 0));

#if 0
  printf ("Changing byte %d in message %d to %c\n",
          byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
#endif
  
  _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
  *expected_validity = DBUS_VALIDITY_UNKNOWN;
  return TRUE;
}
Ejemplo n.º 6
0
static void
test_max_len (DBusString *str,
              int         max_len)
{
  if (max_len > 0)
    {
      if (!_dbus_string_set_length (str, max_len - 1))
        _dbus_assert_not_reached ("setting len to one less than max should have worked");
    }

  if (!_dbus_string_set_length (str, max_len))
    _dbus_assert_not_reached ("setting len to max len should have worked");

  if (_dbus_string_set_length (str, max_len + 1))
    _dbus_assert_not_reached ("setting len to one more than max len should not have worked");

  if (!_dbus_string_set_length (str, 0))
    _dbus_assert_not_reached ("setting len to zero should have worked");
}
Ejemplo n.º 7
0
/**
 * Re-initializes a header that was previously initialized and never
 * freed.  After this, to make the header valid you have to call
 * _dbus_header_create().
 *
 * @param header header to re-initialize
 * @param byte_order byte order of the header
 */
void
_dbus_header_reinit (DBusHeader *header,
                     int         byte_order)
{
  _dbus_string_set_length (&header->data, 0);

  header->byte_order = byte_order;
  header->padding = 0;

  _dbus_header_cache_invalidate_all (header);
}
Ejemplo n.º 8
0
/**
 * Thin wrapper around the read() system call that appends
 * the data it reads to the DBusString buffer. It appends
 * up to the given count.
 * 
 * @param hnd the HANDLE to read from
 * @param buffer the buffer to append data to
 * @param count the amount of data to read
 * @param error place to set an error
 * @returns the number of bytes read or -1
 */
static int
_dbus_file_read (HANDLE            hnd,
                 DBusString       *buffer,
                 int               count,
                 DBusError        *error)
{
  BOOL result;
  DWORD bytes_read;
  int start;
  char *data;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  _dbus_assert (count >= 0);

  start = _dbus_string_get_length (buffer);

  if (!_dbus_string_lengthen (buffer, count))
    {
      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
      return -1;
    }

  data = _dbus_string_get_data_len (buffer, start, count);

  result = ReadFile (hnd, data, count, &bytes_read, NULL);
  if (result == 0)
    {
      char *emsg = _dbus_win_error_string (GetLastError ());
      dbus_set_error (error, _dbus_win_error_from_last_error (),
                      "Failed to read from 0x%x: %s", hnd, emsg);
      _dbus_win_free_error_string (emsg);
      return -1;
    }

  if (bytes_read)
    {
      /* put length back (doesn't actually realloc) */
      _dbus_string_set_length (buffer, start + bytes_read);

#if 0
      if (bytes_read > 0)
        _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
#endif
    }

  return bytes_read;
}
Ejemplo n.º 9
0
static dbus_bool_t
generate_byte_changed (DBusMessageDataIter *iter,
                       DBusString          *data,
                       DBusValidity        *expected_validity)
{
  int byte_seq;
  int v_BYTE;

  /* This is a little convoluted to make the bodies the
   * outer loop and each byte of each body the inner
   * loop
   */

 restart:
  if (!generate_many_bodies (iter, data, expected_validity))
    return FALSE;

  iter_recurse (iter);
  byte_seq = iter_get_sequence (iter);
  iter_next (iter);
  iter_unrecurse (iter);
  
  if (byte_seq == _dbus_string_get_length (data))
    {
      _dbus_string_set_length (data, 0);
      /* reset byte count */
      iter_recurse (iter);
      iter_set_sequence (iter, 0);
      iter_unrecurse (iter);
      goto restart;
    }
  else
    {
      /* Undo the "next" in generate_many_bodies */
      iter_set_sequence (iter, iter_get_sequence (iter) - 1);
    }

  _dbus_assert (byte_seq < _dbus_string_get_length (data));
  v_BYTE = _dbus_string_get_byte (data, byte_seq);
  v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
  _dbus_string_set_byte (data, byte_seq, v_BYTE);
  *expected_validity = DBUS_VALIDITY_UNKNOWN;

  return TRUE;
}
Ejemplo n.º 10
0
/**
 * Get next file in the directory. Will not return "." or ".."  on
 * UNIX. If an error occurs, the contents of "filename" are
 * undefined. The error is never set if the function succeeds.
 *
 * This function is not re-entrant, and not necessarily thread-safe.
 * Only use it for test code or single-threaded utilities.
 *
 * @param iter the iterator
 * @param filename string to be set to the next file in the dir
 * @param error return location for error
 * @returns #TRUE if filename was filled in with a new filename
 */
dbus_bool_t
_dbus_directory_get_next_file (DBusDirIter      *iter,
                               DBusString       *filename,
                               DBusError        *error)
{
  struct dirent *ent;
  int err;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

 again:
  errno = 0;
  ent = readdir (iter->d);

  if (!ent)
    {
      err = errno;

      if (err != 0)
        dbus_set_error (error,
                        _dbus_error_from_errno (err),
                        "%s", _dbus_strerror (err));

      return FALSE;
    }
  else if (ent->d_name[0] == '.' &&
           (ent->d_name[1] == '\0' ||
            (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
    goto again;
  else
    {
      _dbus_string_set_length (filename, 0);
      if (!_dbus_string_append (filename, ent->d_name))
        {
          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
                          "No memory to read directory entry");
          return FALSE;
        }
      else
        {
          return TRUE;
        }
    }
}
Ejemplo n.º 11
0
static void
randomly_add_one_byte (const DBusString *orig_data,
                       DBusString       *mutated)
{
  int i;

  if (orig_data != mutated)
    {
      _dbus_string_set_length (mutated, 0);
      
      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
        _dbus_assert_not_reached ("out of mem");
    }

  i = random_int_in_range (0, _dbus_string_get_length (mutated));

  _dbus_string_insert_bytes (mutated, i, 1,
			     random_int_in_range (0, 256));
}
Ejemplo n.º 12
0
static void
randomly_remove_one_byte (const DBusString *orig_data,
                          DBusString       *mutated)
{
  int i;

  if (orig_data != mutated)
    {
      _dbus_string_set_length (mutated, 0);
      
      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
        _dbus_assert_not_reached ("out of mem");
    }

  if (_dbus_string_get_length (mutated) == 0)
    return;
  
  i = random_int_in_range (0, _dbus_string_get_length (mutated));

  _dbus_string_delete (mutated, i, 1);
}
Ejemplo n.º 13
0
static void
randomly_modify_length (const DBusString *orig_data,
                        DBusString       *mutated)
{
  int i;
  int byte_order;
  const char *d;
  dbus_uint32_t orig;
  int delta;
  
  if (orig_data != mutated)
    {
      _dbus_string_set_length (mutated, 0);
      
      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
        _dbus_assert_not_reached ("out of mem");
    }

  if (_dbus_string_get_length (mutated) < 12)
    return;
  
  d = _dbus_string_get_const_data (mutated);

  if (!(*d == DBUS_LITTLE_ENDIAN ||
        *d == DBUS_BIG_ENDIAN))
    return;

  byte_order = *d;
  
  i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
  i = _DBUS_ALIGN_VALUE (i, 4);

  orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);

  delta = random_int_in_range (-10, 10);  
  
  _dbus_marshal_set_uint32 (mutated, byte_order, i,
                            (unsigned) (orig + delta));
}
Ejemplo n.º 14
0
static void
randomly_shorten_or_lengthen (const DBusString *orig_data,
                              DBusString       *mutated)
{
  int delta;

  if (orig_data != mutated)
    {
      _dbus_string_set_length (mutated, 0);
      
      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
        _dbus_assert_not_reached ("out of mem");
    }

  if (_dbus_string_get_length (mutated) == 0)
    delta = random_int_in_range (0, 10);
  else
    delta = random_int_in_range (- _dbus_string_get_length (mutated),
                                 _dbus_string_get_length (mutated) * 3);
  
  if (delta < 0)
    _dbus_string_shorten (mutated, - delta);
  else if (delta > 0)
    {
      int i = 0;

      i = _dbus_string_get_length (mutated);
      if (!_dbus_string_lengthen (mutated, delta))
        _dbus_assert_not_reached ("couldn't lengthen string");

      while (i < _dbus_string_get_length (mutated))
        {
          _dbus_string_set_byte (mutated,
                                 i,
                                 random_int_in_range (0, 256));
          ++i;
        }
    }
}
Ejemplo n.º 15
0
static void
randomly_do_n_things (const DBusString *orig_data,
                      DBusString       *mutated,
                      int               n)
{
  int i;
  void (* functions[]) (const DBusString *orig_data,
                        DBusString       *mutated) =
    {
      randomly_shorten_or_lengthen,
      randomly_change_one_byte,
      randomly_add_one_byte,
      randomly_remove_one_byte,
      randomly_modify_length,
      randomly_set_extreme_ints,
      randomly_change_one_type
    };

  _dbus_string_set_length (mutated, 0);

  if (!_dbus_string_copy (orig_data, 0, mutated, 0))
    _dbus_assert_not_reached ("out of mem");

  i = 0;
  while (i < n)
    {
      int which;

      which = random_int_in_range (0, _DBUS_N_ELEMENTS (functions));

      (* functions[which]) (mutated, mutated);
      times_we_did_each_thing[which] += 1;
      
      ++i;
    }
}
Ejemplo n.º 16
0
static void
randomly_change_one_type (const DBusString *orig_data,
                          DBusString       *mutated)
{
  int i;
  int len;
  
  if (orig_data != mutated)
    {
      _dbus_string_set_length (mutated, 0);
      
      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
        _dbus_assert_not_reached ("out of mem");
    }

  if (_dbus_string_get_length (mutated) == 0)
    return;

  len = _dbus_string_get_length (mutated);
  i = random_int_in_range (0, len);

  /* Look for a type starting at a random location,
   * and replace with a different type
   */
  while (i < len)
    {
      int b;
      b = _dbus_string_get_byte (mutated, i);
      if (dbus_type_is_valid (b))
        {
          _dbus_string_set_byte (mutated, i, random_type ());
          return;
        }
      ++i;
    }
}
Ejemplo n.º 17
0
/**
 * @ingroup DBusStringInternals
 * Unit test for DBusString.
 *
 * @todo Need to write tests for _dbus_string_copy() and
 * _dbus_string_move() moving to/from each of start/middle/end of a
 * string. Also need tests for _dbus_string_move_len ()
 * 
 * @returns #TRUE on success.
 */
dbus_bool_t
_dbus_string_test (void)
{
  DBusString str;
  DBusString other;
  int i, end;
  long v;
  double d;
  int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
  char *s;
  dbus_unichar_t ch;
  
  i = 0;
  while (i < _DBUS_N_ELEMENTS (lens))
    {
      if (!_dbus_string_init (&str))
        _dbus_assert_not_reached ("failed to init string");

      set_max_length (&str, lens[i]);
      
      test_max_len (&str, lens[i]);
      _dbus_string_free (&str);

      ++i;
    }

  /* Test shortening and setting length */
  i = 0;
  while (i < _DBUS_N_ELEMENTS (lens))
    {
      int j;
      
      if (!_dbus_string_init (&str))
        _dbus_assert_not_reached ("failed to init string");

      set_max_length (&str, lens[i]);
      
      if (!_dbus_string_set_length (&str, lens[i]))
        _dbus_assert_not_reached ("failed to set string length");

      j = lens[i];
      while (j > 0)
        {
          _dbus_assert (_dbus_string_get_length (&str) == j);
          if (j > 0)
            {
              _dbus_string_shorten (&str, 1);
              _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
            }
          --j;
        }
      
      _dbus_string_free (&str);

      ++i;
    }

  /* Test equality */
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("oom");

  if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("oom");

  _dbus_string_init_const (&other, "H");
  _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0));
  _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1));
  _dbus_string_init_const (&other, "Hello");
  _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0));
  _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1));
  _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2));
  _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3));
  _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4));
  _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5));

  _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0));
  _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1));
  _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2));
  _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3));
  _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4));
  _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5));

  
  _dbus_string_init_const (&other, "World");
  _dbus_assert (_dbus_string_equal_substring (&str, 6,  5, &other, 0));
  _dbus_assert (_dbus_string_equal_substring (&str, 7,  4, &other, 1));
  _dbus_assert (_dbus_string_equal_substring (&str, 8,  3, &other, 2));
  _dbus_assert (_dbus_string_equal_substring (&str, 9,  2, &other, 3));
  _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4));
  _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5));

  _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6));
  _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7));
  _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8));
  _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9));
  _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10));
  _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11));
  
  _dbus_string_free (&str);
  
  /* Test appending data */
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");

  i = 0;
  while (i < 10)
    {
      if (!_dbus_string_append (&str, "a"))
        _dbus_assert_not_reached ("failed to append string to string\n");

      _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);

      if (!_dbus_string_append_byte (&str, 'b'))
        _dbus_assert_not_reached ("failed to append byte to string\n");

      _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
                    
      ++i;
    }

  _dbus_string_free (&str);

  /* Check steal_data */
  
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");

  if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("could not append to string");

  i = _dbus_string_get_length (&str);
  
  if (!_dbus_string_steal_data (&str, &s))
    _dbus_assert_not_reached ("failed to steal data");

  _dbus_assert (_dbus_string_get_length (&str) == 0);
  _dbus_assert (((int)strlen (s)) == i);

  dbus_free (s);

  /* Check move */
  
  if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("could not append to string");

  i = _dbus_string_get_length (&str);

  if (!_dbus_string_init (&other))
    _dbus_assert_not_reached ("could not init string");
  
  if (!_dbus_string_move (&str, 0, &other, 0))
    _dbus_assert_not_reached ("could not move");

  _dbus_assert (_dbus_string_get_length (&str) == 0);
  _dbus_assert (_dbus_string_get_length (&other) == i);

  if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("could not append to string");
  
  if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
    _dbus_assert_not_reached ("could not move");

  _dbus_assert (_dbus_string_get_length (&str) == 0);
  _dbus_assert (_dbus_string_get_length (&other) == i * 2);

    if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("could not append to string");
  
  if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
    _dbus_assert_not_reached ("could not move");

  _dbus_assert (_dbus_string_get_length (&str) == 0);
  _dbus_assert (_dbus_string_get_length (&other) == i * 3);
  
  _dbus_string_free (&other);

  /* Check copy */
  
  if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("could not append to string");

  i = _dbus_string_get_length (&str);
  
  if (!_dbus_string_init (&other))
    _dbus_assert_not_reached ("could not init string");
  
  if (!_dbus_string_copy (&str, 0, &other, 0))
    _dbus_assert_not_reached ("could not copy");

  _dbus_assert (_dbus_string_get_length (&str) == i);
  _dbus_assert (_dbus_string_get_length (&other) == i);

  if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
    _dbus_assert_not_reached ("could not copy");

  _dbus_assert (_dbus_string_get_length (&str) == i);
  _dbus_assert (_dbus_string_get_length (&other) == i * 2);
  _dbus_assert (_dbus_string_equal_c_str (&other,
                                          "Hello WorldHello World"));

  if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
    _dbus_assert_not_reached ("could not copy");

  _dbus_assert (_dbus_string_get_length (&str) == i);
  _dbus_assert (_dbus_string_get_length (&other) == i * 3);
  _dbus_assert (_dbus_string_equal_c_str (&other,
                                          "Hello WorldHello WorldHello World"));
  
  _dbus_string_free (&str);
  _dbus_string_free (&other);

  /* Check replace */

  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");
  
  if (!_dbus_string_append (&str, "Hello World"))
    _dbus_assert_not_reached ("could not append to string");

  i = _dbus_string_get_length (&str);
  
  if (!_dbus_string_init (&other))
    _dbus_assert_not_reached ("could not init string");
  
  if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
                                 &other, 0, _dbus_string_get_length (&other)))
    _dbus_assert_not_reached ("could not replace");

  _dbus_assert (_dbus_string_get_length (&str) == i);
  _dbus_assert (_dbus_string_get_length (&other) == i);
  _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
  
  if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
                                 &other, 5, 1))
    _dbus_assert_not_reached ("could not replace center space");

  _dbus_assert (_dbus_string_get_length (&str) == i);
  _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
  _dbus_assert (_dbus_string_equal_c_str (&other,
                                          "HelloHello WorldWorld"));

  
  if (!_dbus_string_replace_len (&str, 1, 1,
                                 &other,
                                 _dbus_string_get_length (&other) - 1,
                                 1))
    _dbus_assert_not_reached ("could not replace end character");
  
  _dbus_assert (_dbus_string_get_length (&str) == i);
  _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
  _dbus_assert (_dbus_string_equal_c_str (&other,
                                          "HelloHello WorldWorle"));
  
  _dbus_string_free (&str);
  _dbus_string_free (&other);
  
  /* Check append/get unichar */
  
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");

  ch = 0;
  if (!_dbus_string_append_unichar (&str, 0xfffc))
    _dbus_assert_not_reached ("failed to append unichar");

  _dbus_string_get_unichar (&str, 0, &ch, &i);

  _dbus_assert (ch == 0xfffc);
  _dbus_assert (i == _dbus_string_get_length (&str));

  _dbus_string_free (&str);

  /* Check insert/set/get byte */
  
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");

  if (!_dbus_string_append (&str, "Hello"))
    _dbus_assert_not_reached ("failed to append Hello");

  _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
  _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
  _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
  _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
  _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');

  _dbus_string_set_byte (&str, 1, 'q');
  _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');

  if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
    _dbus_assert_not_reached ("can't insert byte");

  if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
    _dbus_assert_not_reached ("can't insert byte");

  if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
    _dbus_assert_not_reached ("can't insert byte");
  
  _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
  _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
  _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
  _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
  _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
  _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
  _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
  _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
  _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
  _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
  _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');

  _dbus_string_free (&str);
  
  /* Check append/parse int/double */
  
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");

  if (!_dbus_string_append_int (&str, 27))
    _dbus_assert_not_reached ("failed to append int");

  i = _dbus_string_get_length (&str);

  if (!_dbus_string_parse_int (&str, 0, &v, &end))
    _dbus_assert_not_reached ("failed to parse int");

  _dbus_assert (v == 27);
  _dbus_assert (end == i);

  _dbus_string_free (&str);
  
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");
  
  if (!_dbus_string_append_double (&str, 50.3))
    _dbus_assert_not_reached ("failed to append float");

  i = _dbus_string_get_length (&str);

  if (!_dbus_string_parse_double (&str, 0, &d, &end))
    _dbus_assert_not_reached ("failed to parse float");

  _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
  _dbus_assert (end == i);

  _dbus_string_free (&str);

  /* Test find */
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("failed to init string");

  if (!_dbus_string_append (&str, "Hello"))
    _dbus_assert_not_reached ("couldn't append to string");
  
  if (!_dbus_string_find (&str, 0, "He", &i))
    _dbus_assert_not_reached ("didn't find 'He'");
  _dbus_assert (i == 0);

  if (!_dbus_string_find (&str, 0, "Hello", &i))
    _dbus_assert_not_reached ("didn't find 'Hello'");
  _dbus_assert (i == 0);
  
  if (!_dbus_string_find (&str, 0, "ello", &i))
    _dbus_assert_not_reached ("didn't find 'ello'");
  _dbus_assert (i == 1);

  if (!_dbus_string_find (&str, 0, "lo", &i))
    _dbus_assert_not_reached ("didn't find 'lo'");
  _dbus_assert (i == 3);

  if (!_dbus_string_find (&str, 2, "lo", &i))
    _dbus_assert_not_reached ("didn't find 'lo'");
  _dbus_assert (i == 3);

  if (_dbus_string_find (&str, 4, "lo", &i))
    _dbus_assert_not_reached ("did find 'lo'");
  
  if (!_dbus_string_find (&str, 0, "l", &i))
    _dbus_assert_not_reached ("didn't find 'l'");
  _dbus_assert (i == 2);

  if (!_dbus_string_find (&str, 0, "H", &i))
    _dbus_assert_not_reached ("didn't find 'H'");
  _dbus_assert (i == 0);

  if (!_dbus_string_find (&str, 0, "", &i))
    _dbus_assert_not_reached ("didn't find ''");
  _dbus_assert (i == 0);
  
  if (_dbus_string_find (&str, 0, "Hello!", NULL))
    _dbus_assert_not_reached ("Did find 'Hello!'");

  if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
    _dbus_assert_not_reached ("Did find 'Oh, Hello'");
  
  if (_dbus_string_find (&str, 0, "ill", NULL))
    _dbus_assert_not_reached ("Did find 'ill'");

  if (_dbus_string_find (&str, 0, "q", NULL))
    _dbus_assert_not_reached ("Did find 'q'");

  if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
    _dbus_assert_not_reached ("Didn't find 'He'");

  if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
    _dbus_assert_not_reached ("Did find 'Hello'");

  if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
    _dbus_assert_not_reached ("Did not find 'H'");
  _dbus_assert (i == 0);

  if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
    _dbus_assert_not_reached ("Did not find 'o'");
  _dbus_assert (i == _dbus_string_get_length (&str) - 1);

  if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
    _dbus_assert_not_reached ("Did find 'o'");
  _dbus_assert (i == -1);

  if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
    _dbus_assert_not_reached ("Did find 'e'");
  _dbus_assert (i == -1);

  if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
    _dbus_assert_not_reached ("Didn't find 'e'");
  _dbus_assert (i == 1);
  
  _dbus_string_free (&str);

  /* Hex encoding */
  _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
  if (!_dbus_string_init (&other))
    _dbus_assert_not_reached ("could not init string");

  if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
    _dbus_assert_not_reached ("deccoded bogus hex string with no error");

  _dbus_assert (end == 8);

  _dbus_string_free (&other);

  test_roundtrips (test_hex_roundtrip);
  
  _dbus_string_free (&str);

  {                                                                                           
    int found, found_len;  

    _dbus_string_init_const (&str, "012\r\n567\n90");
    
    if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2)
      _dbus_assert_not_reached ("Did not find '\\r\\n'");                                       
    if (found != 3 || found_len != 2)                                                           
      _dbus_assert_not_reached ("invalid return values");                                       
    
    if (!_dbus_string_find_eol (&str, 5, &found, &found_len))                                    
      _dbus_assert_not_reached ("Did not find '\\n'");                                          
    if (found != 8 || found_len != 1)                                                           
      _dbus_assert_not_reached ("invalid return values");                                       
    
    if (_dbus_string_find_eol (&str, 9, &found, &found_len))                                     
      _dbus_assert_not_reached ("Found not expected '\\n'");                                    
    else if (found != 11 || found_len != 0)                                                     
      _dbus_assert_not_reached ("invalid return values '\\n'");                                 

    found = -1;
    found_len = -1;
    _dbus_string_init_const (&str, "");
    if (_dbus_string_find_eol (&str, 0, &found, &found_len))
      _dbus_assert_not_reached ("found an eol in an empty string");
    _dbus_assert (found == 0);
    _dbus_assert (found_len == 0);
    
    found = -1;
    found_len = -1;
    _dbus_string_init_const (&str, "foobar");
    if (_dbus_string_find_eol (&str, 0, &found, &found_len))
      _dbus_assert_not_reached ("found eol in string that lacks one");
    _dbus_assert (found == 6);
    _dbus_assert (found_len == 0);

    found = -1;
    found_len = -1;
    _dbus_string_init_const (&str, "foobar\n");
    if (!_dbus_string_find_eol (&str, 0, &found, &found_len))
      _dbus_assert_not_reached ("did not find eol in string that has one at end");
    _dbus_assert (found == 6);
    _dbus_assert (found_len == 1);
  }

  {
    DBusString line;

#define FIRST_LINE "this is a line"
#define SECOND_LINE "this is a second line"
    /* third line is empty */
#define THIRD_LINE ""
#define FOURTH_LINE "this is a fourth line"
    
    if (!_dbus_string_init (&str))
      _dbus_assert_not_reached ("no memory");

    if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE))
      _dbus_assert_not_reached ("no memory");
    
    if (!_dbus_string_init (&line))
      _dbus_assert_not_reached ("no memory");
    
    if (!_dbus_string_pop_line (&str, &line))
      _dbus_assert_not_reached ("failed to pop first line");

    _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE));
    
    if (!_dbus_string_pop_line (&str, &line))
      _dbus_assert_not_reached ("failed to pop second line");

    _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE));
    
    if (!_dbus_string_pop_line (&str, &line))
      _dbus_assert_not_reached ("failed to pop third line");

    _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE));
    
    if (!_dbus_string_pop_line (&str, &line))
      _dbus_assert_not_reached ("failed to pop fourth line");

    _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE));
    
    _dbus_string_free (&str);
    _dbus_string_free (&line);
  }

  {
    if (!_dbus_string_init (&str))
      _dbus_assert_not_reached ("no memory");

    for (i = 0; i < 10000; i++)
      if (!_dbus_string_append (&str, "abcdefghijklmnopqrstuvwxyz"))
        _dbus_assert_not_reached ("no memory");

    if (!_dbus_string_set_length (&str, 10))
      _dbus_assert_not_reached ("failed to set length");

    /* actually compact */
    if (!_dbus_string_compact (&str, 2048))
      _dbus_assert_not_reached ("failed to compact after set_length");

    /* peek inside to make sure it worked */
    if (((DBusRealString *)&str)->allocated > 30)
      _dbus_assert_not_reached ("compacting string didn't do anything");

    if (!_dbus_string_equal_c_str (&str, "abcdefghij"))
      _dbus_assert_not_reached ("unexpected content after compact");

    /* compact nothing */
    if (!_dbus_string_compact (&str, 2048))
      _dbus_assert_not_reached ("failed to compact 2nd time");

    if (!_dbus_string_equal_c_str (&str, "abcdefghij"))
      _dbus_assert_not_reached ("unexpected content after 2nd compact");

    /* and make sure it still works...*/
    if (!_dbus_string_append (&str, "123456"))
      _dbus_assert_not_reached ("failed to append after compact");

    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456"))
      _dbus_assert_not_reached ("unexpected content after append");

    /* after growing automatically, this should do nothing */
    if (!_dbus_string_compact (&str, 20000))
      _dbus_assert_not_reached ("failed to compact after grow");

    /* but this one will do something */
    if (!_dbus_string_compact (&str, 0))
      _dbus_assert_not_reached ("failed to compact after grow");

    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456"))
      _dbus_assert_not_reached ("unexpected content");

    if (!_dbus_string_append (&str, "!@#$%"))
      _dbus_assert_not_reached ("failed to append after compact");

    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456!@#$%"))
      _dbus_assert_not_reached ("unexpected content");

    _dbus_string_free (&str);
  }

  {
    const char two_strings[] = "one\ttwo";

    if (!_dbus_string_init (&str))
      _dbus_assert_not_reached ("no memory");

    if (!_dbus_string_init (&other))
      _dbus_assert_not_reached ("no memory");

    if (!_dbus_string_append (&str, two_strings))
      _dbus_assert_not_reached ("no memory");

    if (!_dbus_string_split_on_byte (&str, '\t', &other))
      _dbus_assert_not_reached ("no memory or delimiter not found");

    if (strcmp (_dbus_string_get_data (&str), "one") != 0)
      _dbus_assert_not_reached ("left side after split on tab is wrong");

    if (strcmp (_dbus_string_get_data (&other), "two") != 0)
      _dbus_assert_not_reached ("right side after split on tab is wrong");

    _dbus_string_free (&str);
    _dbus_string_free (&other);
  }
  
  return TRUE;
}
Ejemplo n.º 18
0
/**
 * Creates a message header from potentially-untrusted data. The
 * return value is #TRUE if there was enough memory and the data was
 * valid. If it returns #TRUE, the header will be created. If it
 * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR, 
 * then there wasn't enough memory.  If it returns #FALSE 
 * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was 
 * invalid.
 *
 * The byte_order, fields_array_len, and body_len args should be from
 * _dbus_header_have_message_untrusted(). Validation performed in
 * _dbus_header_have_message_untrusted() is assumed to have been
 * already done.
 *
 * @param header the header (must be initialized)
 * @param mode whether to do validation
 * @param validity return location for invalidity reason
 * @param byte_order byte order from header
 * @param fields_array_len claimed length of fields array
 * @param body_len claimed length of body
 * @param header_len claimed length of header
 * @param str a string
 * @param start start of header, 8-aligned
 * @param len length of string to look at
 * @returns #FALSE if no memory or data was invalid, #TRUE otherwise
 */
dbus_bool_t
_dbus_header_load (DBusHeader        *header,
                   DBusValidationMode mode,
                   DBusValidity      *validity,
                   int                byte_order,
                   int                fields_array_len,
                   int                header_len,
                   int                body_len,
                   const DBusString  *str,
                   int                start,
                   int                len)
{
  int leftover;
  DBusValidity v;
  DBusTypeReader reader;
  DBusTypeReader array_reader;
  unsigned char v_byte;
  dbus_uint32_t v_uint32;
  dbus_uint32_t serial;
  int padding_start;
  int padding_len;
  int i;

  _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
  _dbus_assert (header_len <= len);
  _dbus_assert (_dbus_string_get_length (&header->data) == 0);

  if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
    {
      _dbus_verbose ("Failed to copy buffer into new header\n");
      *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
      return FALSE;
    }

  if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
    {
      leftover = len - header_len - body_len - start;
    }
  else
    {
      v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
                                           byte_order,
                                           &leftover,
                                           str, start, len);
      
      if (v != DBUS_VALID)
        {
          *validity = v;
          goto invalid;
        }
    }

  _dbus_assert (leftover < len);

  padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
  padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
  _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
  _dbus_assert (start + header_len == padding_start + padding_len);

  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
    {
      if (!_dbus_string_validate_nul (str, padding_start, padding_len))
        {
          *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
          goto invalid;
        }
    }

  header->padding = padding_len;

  if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
    {
      *validity = DBUS_VALID;
      return TRUE;
    }

  /* We now know the data is well-formed, but we have to check that
   * it's valid.
   */

  _dbus_type_reader_init (&reader,
                          byte_order,
                          &_dbus_header_signature_str, 0,
                          str, start);

  /* BYTE ORDER */
  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
  _dbus_type_reader_read_basic (&reader, &v_byte);
  _dbus_type_reader_next (&reader);

  _dbus_assert (v_byte == byte_order);
  header->byte_order = byte_order;

  /* MESSAGE TYPE */
  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
  _dbus_type_reader_read_basic (&reader, &v_byte);
  _dbus_type_reader_next (&reader);

  /* unknown message types are supposed to be ignored, so only validation here is
   * that it isn't invalid
   */
  if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
    {
      *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
      goto invalid;
    }

  /* FLAGS */
  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
  _dbus_type_reader_read_basic (&reader, &v_byte);
  _dbus_type_reader_next (&reader);

  /* unknown flags should be ignored */

  /* PROTOCOL VERSION */
  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
  _dbus_type_reader_read_basic (&reader, &v_byte);
  _dbus_type_reader_next (&reader);

  if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
    {
      *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
      goto invalid;
    }

  /* BODY LENGTH */
  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
  _dbus_type_reader_read_basic (&reader, &v_uint32);
  _dbus_type_reader_next (&reader);

  _dbus_assert (body_len == (signed) v_uint32);

  /* SERIAL */
  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
  _dbus_type_reader_read_basic (&reader, &serial);
  _dbus_type_reader_next (&reader);

  if (serial == 0)
    {
      *validity = DBUS_INVALID_BAD_SERIAL;
      goto invalid;
    }

  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);

  _dbus_type_reader_recurse (&reader, &array_reader);
  while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
    {
      DBusTypeReader struct_reader;
      DBusTypeReader variant_reader;
      unsigned char field_code;

      _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);

      _dbus_type_reader_recurse (&array_reader, &struct_reader);

      _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
      _dbus_type_reader_read_basic (&struct_reader, &field_code);
      _dbus_type_reader_next (&struct_reader);

      if (field_code == DBUS_HEADER_FIELD_INVALID)
        {
          _dbus_verbose ("invalid header field code\n");
          *validity = DBUS_INVALID_HEADER_FIELD_CODE;
          goto invalid;
        }

      if (field_code > DBUS_HEADER_FIELD_LAST)
        {
          _dbus_verbose ("unknown header field code %d, skipping\n",
                         field_code);
          goto next_field;
        }

      _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
      _dbus_type_reader_recurse (&struct_reader, &variant_reader);

      v = load_and_validate_field (header, field_code, &variant_reader);
      if (v != DBUS_VALID)
        {
          _dbus_verbose ("Field %d was invalid\n", field_code);
          *validity = v;
          goto invalid;
        }

    next_field:
      _dbus_type_reader_next (&array_reader);
    }

  /* Anything we didn't fill in is now known not to exist */
  i = 0;
  while (i <= DBUS_HEADER_FIELD_LAST)
    {
      if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
        header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
      ++i;
    }

  v = check_mandatory_fields (header);
  if (v != DBUS_VALID)
    {
      _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
      *validity = v;
      goto invalid;
    }

  *validity = DBUS_VALID;
  return TRUE;

 invalid:
  _dbus_string_set_length (&header->data, 0);
  return FALSE;
}
Ejemplo n.º 19
0
static dbus_bool_t
generate_uint32_changed (DBusMessageDataIter *iter,
                         DBusString          *data,
                         DBusValidity        *expected_validity)
{
  int body_seq;
  int byte_seq;
  int change_seq;
  dbus_uint32_t v_UINT32;
  int byte_order;
  const UIntChange *change;
  int base_depth;

  /* Outer loop is each body, next loop is each change,
   * inner loop is each change location
   */

  base_depth = iter->depth;
  
 next_body:
  _dbus_assert (iter->depth == (base_depth + 0));
  _dbus_string_set_length (data, 0);
  body_seq = iter_get_sequence (iter);
  
  if (!generate_many_bodies (iter, data, expected_validity))
    return FALSE;

  _dbus_assert (iter->depth == (base_depth + 0));

  iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
  iter_recurse (iter);
 next_change:
  _dbus_assert (iter->depth == (base_depth + 1));
  change_seq = iter_get_sequence (iter);
  
  if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
    {
      /* Reset change count */
      iter_set_sequence (iter, 0);
      iter_unrecurse (iter);
      iter_next (iter);
      goto next_body;
    }

  _dbus_assert (iter->depth == (base_depth + 1));
  
  iter_recurse (iter);
  _dbus_assert (iter->depth == (base_depth + 2));
  byte_seq = iter_get_sequence (iter);
  /* skip 4 bytes at a time */
  iter_next (iter);
  iter_next (iter);
  iter_next (iter);
  iter_next (iter);
  iter_unrecurse (iter);

  _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
  if (byte_seq >= (_dbus_string_get_length (data) - 4))
    {
      /* reset byte count */
      _dbus_assert (iter->depth == (base_depth + 1));
      iter_recurse (iter);
      _dbus_assert (iter->depth == (base_depth + 2));
      iter_set_sequence (iter, 0);
      iter_unrecurse (iter);
      _dbus_assert (iter->depth == (base_depth + 1));
      iter_next (iter);
      goto next_change;
    }
  
  _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));

  byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
  
  v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);

  change = &uint32_changes[change_seq];

  if (change->type == CHANGE_TYPE_ADJUST)
    {
      v_UINT32 += (int) change->value;
    }
  else
    {
      v_UINT32 = change->value;
    }

#if 0
  printf ("body %d change %d pos %d ",
          body_seq, change_seq, byte_seq);

  if (change->type == CHANGE_TYPE_ADJUST)
    printf ("adjust by %d", (int) change->value);
  else
    printf ("set to %u", change->value);
  
  printf (" \t%u -> %u\n",
          _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
          v_UINT32);
#endif
  
  _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
  *expected_validity = DBUS_VALIDITY_UNKNOWN;

  _dbus_assert (iter->depth == (base_depth + 1));
  iter_unrecurse (iter);
  _dbus_assert (iter->depth == (base_depth + 0));
          
  return TRUE;
}
Ejemplo n.º 20
0
static dbus_bool_t
generate_wrong_length (DBusMessageDataIter *iter,
                       DBusString          *data,
                       DBusValidity        *expected_validity)
{
  int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
                    1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
  int adjust;
  int len_seq;

 restart:
  len_seq = iter_get_sequence (iter);
  if (len_seq == _DBUS_N_ELEMENTS (lengths))
    return FALSE;

  _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
  
  iter_recurse (iter);
  if (!generate_many_bodies (iter, data, expected_validity))
    {
      iter_set_sequence (iter, 0); /* reset to first body */
      iter_unrecurse (iter);
      iter_next (iter);            /* next length adjustment */
      goto restart;
    }
  iter_unrecurse (iter);

  adjust = lengths[len_seq];

  if (adjust < 0)
    {
      if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
        _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
      else
        _dbus_string_shorten (data, - adjust);
      *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
    }
  else
    {      
      if (!_dbus_string_lengthen (data, adjust))
        _dbus_assert_not_reached ("oom");
      *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
    }

  /* Fixup lengths */
  {
    int old_body_len;
    int new_body_len;
    int byte_order;
    
    _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
    
    byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
    old_body_len = _dbus_marshal_read_uint32 (data,
                                              BODY_LENGTH_OFFSET,
                                              byte_order,
                                              NULL);
    _dbus_assert (old_body_len < _dbus_string_get_length (data));
    new_body_len = old_body_len + adjust;
    if (new_body_len < 0)
      {
        new_body_len = 0;
        /* we just munged the header, and aren't sure how */
        *expected_validity = DBUS_VALIDITY_UNKNOWN;
      }

    _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
                   old_body_len, new_body_len, adjust);
    
    _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
                              new_body_len,
                              byte_order);
  }

  return TRUE;
}
Ejemplo n.º 21
0
static void
do_byteswap_test (int byte_order)
{
  int sequence;
  DBusString signature;
  DBusString body;
  int opposite_order;

  if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
    _dbus_assert_not_reached ("oom");

  opposite_order = byte_order == DBUS_LITTLE_ENDIAN ? DBUS_BIG_ENDIAN : DBUS_LITTLE_ENDIAN;
  
  sequence = 0;
  while (dbus_internal_do_not_use_generate_bodies (sequence,
                                                   byte_order,
                                                   &signature, &body))
    {
      DBusString copy;
      DBusTypeReader body_reader;
      DBusTypeReader copy_reader;

      if (!_dbus_string_init (&copy))
        _dbus_assert_not_reached ("oom");

      if (!_dbus_string_copy (&body, 0, &copy, 0))
        _dbus_assert_not_reached ("oom");

      _dbus_marshal_byteswap (&signature, 0,
                              byte_order,
                              opposite_order,
                              &copy, 0);

      _dbus_type_reader_init (&body_reader, byte_order, &signature, 0,
                              &body, 0);
      _dbus_type_reader_init (&copy_reader, opposite_order, &signature, 0,
                              &copy, 0);
      
      if (!_dbus_type_reader_equal_values (&body_reader, &copy_reader))
        {
          _dbus_verbose_bytes_of_string (&signature, 0,
                                         _dbus_string_get_length (&signature));
          _dbus_verbose_bytes_of_string (&body, 0,
                                         _dbus_string_get_length (&body));
          _dbus_verbose_bytes_of_string (&copy, 0,
                                         _dbus_string_get_length (&copy));

          _dbus_warn ("Byte-swapped data did not have same values as original data");
          _dbus_assert_not_reached ("test failed");
        }
      
      _dbus_string_free (&copy);
      
      _dbus_string_set_length (&signature, 0);
      _dbus_string_set_length (&body, 0);
      ++sequence;
    }

  _dbus_string_free (&signature);
  _dbus_string_free (&body);

  printf ("  %d blocks swapped from order '%c' to '%c'\n",
          sequence, byte_order, opposite_order);
}
Ejemplo n.º 22
0
dbus_bool_t
_dbus_marshal_validate_test (void)
{
  DBusString str;
  int i;

  const char *valid_paths[] = {
    "/",
    "/foo/bar",
    "/foo",
    "/foo/bar/baz"
  };
  const char *invalid_paths[] = {
    "bar",
    "bar/baz",
    "/foo/bar/",
    "/foo/",
    "foo/",
    "boo//blah",
    "//",
    "///",
    "foo///blah/",
    "Hello World",
    "",
    "   ",
    "foo bar"
  };

  const char *valid_interfaces[] = {
    "org.freedesktop.Foo",
    "Bar.Baz",
    "Blah.Blah.Blah.Blah.Blah",
    "a.b",
    "a.b.c.d.e.f.g",
    "a0.b1.c2.d3.e4.f5.g6",
    "abc123.foo27"
  };
  const char *invalid_interfaces[] = {
    ".",
    "",
    "..",
    ".Foo.Bar",
    "..Foo.Bar",
    "Foo.Bar.",
    "Foo.Bar..",
    "Foo",
    "9foo.bar.baz",
    "foo.bar..baz",
    "foo.bar...baz",
    "foo.bar.b..blah",
    ":",
    ":0-1",
    "10",
    ":11.34324",
    "0.0.0",
    "0..0",
    "foo.Bar.%",
    "foo.Bar!!",
    "!Foo.bar.bz",
    "foo.$.blah",
    "",
    "   ",
    "foo bar"
  };

  const char *valid_unique_names[] = {
    ":0",
    ":a",
    ":",
    ":.a",
    ":.1",
    ":0.1",
    ":000.2222",
    ":.blah",
    ":abce.freedesktop.blah"
  };
  const char *invalid_unique_names[] = {
    //":-",
    ":!",
    //":0-10",
    ":blah.",
    ":blah.",
    ":blah..org",
    ":blah.org..",
    ":..blah.org",
    "",
    "   ",
    "foo bar"
  };

  const char *valid_members[] = {
    "Hello",
    "Bar",
    "foobar",
    "_foobar",
    "foo89"
  };

  const char *invalid_members[] = {
    "9Hello",
    "10",
    "1",
    "foo-bar",
    "blah.org",
    ".blah",
    "blah.",
    "Hello.",
    "!foo",
    "",
    "   ",
    "foo bar"
  };

  const char *valid_signatures[] = {
    "",
    "sss",
    "i",
    "b"
  };

  const char *invalid_signatures[] = {
    " ",
    "not a valid signature",
    "123",
    ".",
    "(",
    "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
  };

  /* Signature with reason */

  run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
                      _dbus_validate_signature_with_reason);

  /* Path validation */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
    {
      _dbus_string_init_const (&str, valid_paths[i]);

      if (!_dbus_validate_path (&str, 0,
                                _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Path \"%s\" should have been valid", valid_paths[i]);
          _dbus_assert_not_reached ("invalid path");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
    {
      _dbus_string_init_const (&str, invalid_paths[i]);

      if (_dbus_validate_path (&str, 0,
                               _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Path \"%s\" should have been invalid", invalid_paths[i]);
          _dbus_assert_not_reached ("valid path");
        }

      ++i;
    }

  /* Interface validation */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
    {
      _dbus_string_init_const (&str, valid_interfaces[i]);

      if (!_dbus_validate_interface (&str, 0,
                                     _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Interface \"%s\" should have been valid", valid_interfaces[i]);
          _dbus_assert_not_reached ("invalid interface");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
    {
      _dbus_string_init_const (&str, invalid_interfaces[i]);

      if (_dbus_validate_interface (&str, 0,
                                    _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Interface \"%s\" should have been invalid", invalid_interfaces[i]);
          _dbus_assert_not_reached ("valid interface");
        }

      ++i;
    }

  /* Bus name validation (check that valid interfaces are valid bus names,
   * and invalid interfaces are invalid services except if they start with ':')
   */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
    {
      _dbus_string_init_const (&str, valid_interfaces[i]);

      if (!_dbus_validate_bus_name (&str, 0,
                                   _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Bus name \"%s\" should have been valid", valid_interfaces[i]);
          _dbus_assert_not_reached ("invalid bus name");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
    {
      if (invalid_interfaces[i][0] != ':')
        {
          _dbus_string_init_const (&str, invalid_interfaces[i]);

          if (_dbus_validate_bus_name (&str, 0,
                                       _dbus_string_get_length (&str)))
            {
              _dbus_warn ("Bus name \"%s\" should have been invalid", invalid_interfaces[i]);
              _dbus_assert_not_reached ("valid bus name");
            }
        }

      ++i;
    }

  /* unique name validation */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
    {
      _dbus_string_init_const (&str, valid_unique_names[i]);

      if (!_dbus_validate_bus_name (&str, 0,
                                    _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Bus name \"%s\" should have been valid", valid_unique_names[i]);
          _dbus_assert_not_reached ("invalid unique name");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
    {
      _dbus_string_init_const (&str, invalid_unique_names[i]);

      if (_dbus_validate_bus_name (&str, 0,
                                   _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Bus name \"%s\" should have been invalid", invalid_unique_names[i]);
          _dbus_assert_not_reached ("valid unique name");
        }

      ++i;
    }


  /* Error name validation (currently identical to interfaces)
   */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
    {
      _dbus_string_init_const (&str, valid_interfaces[i]);

      if (!_dbus_validate_error_name (&str, 0,
                                      _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Error name \"%s\" should have been valid", valid_interfaces[i]);
          _dbus_assert_not_reached ("invalid error name");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
    {
      if (invalid_interfaces[i][0] != ':')
        {
          _dbus_string_init_const (&str, invalid_interfaces[i]);

          if (_dbus_validate_error_name (&str, 0,
                                         _dbus_string_get_length (&str)))
            {
              _dbus_warn ("Error name \"%s\" should have been invalid", invalid_interfaces[i]);
              _dbus_assert_not_reached ("valid error name");
            }
        }

      ++i;
    }

  /* Member validation */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_members))
    {
      _dbus_string_init_const (&str, valid_members[i]);

      if (!_dbus_validate_member (&str, 0,
                                  _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Member \"%s\" should have been valid", valid_members[i]);
          _dbus_assert_not_reached ("invalid member");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
    {
      _dbus_string_init_const (&str, invalid_members[i]);

      if (_dbus_validate_member (&str, 0,
                                 _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Member \"%s\" should have been invalid", invalid_members[i]);
          _dbus_assert_not_reached ("valid member");
        }

      ++i;
    }

  /* Signature validation */
  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
    {
      _dbus_string_init_const (&str, valid_signatures[i]);

      if (!_dbus_validate_signature (&str, 0,
                                     _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Signature \"%s\" should have been valid", valid_signatures[i]);
          _dbus_assert_not_reached ("invalid signature");
        }

      ++i;
    }

  i = 0;
  while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
    {
      _dbus_string_init_const (&str, invalid_signatures[i]);

      if (_dbus_validate_signature (&str, 0,
                                    _dbus_string_get_length (&str)))
        {
          _dbus_warn ("Signature \"%s\" should have been invalid", invalid_signatures[i]);
          _dbus_assert_not_reached ("valid signature");
        }

      ++i;
    }

  /* Validate claimed length longer than real length */
  _dbus_string_init_const (&str, "abc.efg");
  if (_dbus_validate_bus_name (&str, 0, 8))
    _dbus_assert_not_reached ("validated too-long string");
  if (_dbus_validate_interface (&str, 0, 8))
    _dbus_assert_not_reached ("validated too-long string");
  if (_dbus_validate_error_name (&str, 0, 8))
    _dbus_assert_not_reached ("validated too-long string");

  _dbus_string_init_const (&str, "abc");
  if (_dbus_validate_member (&str, 0, 4))
    _dbus_assert_not_reached ("validated too-long string");

  _dbus_string_init_const (&str, "sss");
  if (_dbus_validate_signature (&str, 0, 4))
    _dbus_assert_not_reached ("validated too-long signature");

  /* Validate string exceeding max name length */
  if (!_dbus_string_init (&str))
    _dbus_assert_not_reached ("no memory");

  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
    if (!_dbus_string_append (&str, "abc.def"))
      _dbus_assert_not_reached ("no memory");

  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
    _dbus_assert_not_reached ("validated overmax string");
  if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
    _dbus_assert_not_reached ("validated overmax string");
  if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
    _dbus_assert_not_reached ("validated overmax string");

  /* overlong member */
  _dbus_string_set_length (&str, 0);
  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
    if (!_dbus_string_append (&str, "abc"))
      _dbus_assert_not_reached ("no memory");

  if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
    _dbus_assert_not_reached ("validated overmax string");

  /* overlong unique name */
  _dbus_string_set_length (&str, 0);
  _dbus_string_append (&str, ":");
  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
    if (!_dbus_string_append (&str, "abc"))
      _dbus_assert_not_reached ("no memory");

  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
    _dbus_assert_not_reached ("validated overmax string");

  _dbus_string_free (&str);

  /* Body validation; test basic validation of valid bodies for both endian */
  
  {
    int sequence;
    DBusString signature;
    DBusString body;

    if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
      _dbus_assert_not_reached ("oom");

    sequence = 0;
    while (dbus_internal_do_not_use_generate_bodies (sequence,
                                                     DBUS_LITTLE_ENDIAN,
                                                     &signature, &body))
      {
        DBusValidity validity;

        validity = _dbus_validate_body_with_reason (&signature, 0,
                                                    DBUS_LITTLE_ENDIAN,
                                                    NULL, &body, 0,
                                                    _dbus_string_get_length (&body));
        if (validity != DBUS_VALID)
          {
            _dbus_warn ("invalid code %d expected valid on sequence %d little endian",
                        validity, sequence);
            _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
            _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
            _dbus_assert_not_reached ("test failed");
          }

        _dbus_string_set_length (&signature, 0);
        _dbus_string_set_length (&body, 0);
        ++sequence;
      }
                                                     
    sequence = 0;
    while (dbus_internal_do_not_use_generate_bodies (sequence,
                                                     DBUS_BIG_ENDIAN,
                                                     &signature, &body))
      {
        DBusValidity validity;

        validity = _dbus_validate_body_with_reason (&signature, 0,
                                                    DBUS_BIG_ENDIAN,
                                                    NULL, &body, 0,
                                                    _dbus_string_get_length (&body));
        if (validity != DBUS_VALID)
          {
            _dbus_warn ("invalid code %d expected valid on sequence %d big endian",
                        validity, sequence);
            _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
            _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
            _dbus_assert_not_reached ("test failed");
          }

        _dbus_string_set_length (&signature, 0);
        _dbus_string_set_length (&body, 0);
        ++sequence;
      }

    _dbus_string_free (&signature);
    _dbus_string_free (&body);
  }
  
  return TRUE;
}
/* returns false on oom */
static dbus_bool_t
do_writing (DBusTransport *transport)
{
  int total;
  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
  dbus_bool_t oom;
  
  /* No messages without authentication! */
  if (!_dbus_transport_try_to_authenticate (transport))
    {
      _dbus_verbose ("Not authenticated, not writing anything\n");
      return TRUE;
    }

  if (transport->disconnected)
    {
      _dbus_verbose ("Not connected, not writing anything\n");
      return TRUE;
    }

#if 1
  _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
                 _dbus_connection_has_messages_to_send_unlocked (transport->connection),
                 socket_transport->fd);
#endif
  
  oom = FALSE;
  total = 0;

  while (!transport->disconnected &&
         _dbus_connection_has_messages_to_send_unlocked (transport->connection))
    {
      int bytes_written;
      DBusMessage *message;
      const DBusString *header;
      const DBusString *body;
      int header_len, body_len;
      int total_bytes_to_write;
      
      if (total > socket_transport->max_bytes_written_per_iteration)
        {
          _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
                         total, socket_transport->max_bytes_written_per_iteration);
          goto out;
        }
      
      message = _dbus_connection_get_message_to_send (transport->connection);
      _dbus_assert (message != NULL);
      dbus_message_lock (message);

#if 0
      _dbus_verbose ("writing message %p\n", message);
#endif
      
      _dbus_message_get_network_data (message,
                                      &header, &body);

      header_len = _dbus_string_get_length (header);
      body_len = _dbus_string_get_length (body);

      if (_dbus_auth_needs_encoding (transport->auth))
        {
          /* Does fd passing even make sense with encoded data? */
          _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));

          if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
            {
              if (!_dbus_auth_encode_data (transport->auth,
                                           header, &socket_transport->encoded_outgoing))
                {
                  oom = TRUE;
                  goto out;
                }
              
              if (!_dbus_auth_encode_data (transport->auth,
                                           body, &socket_transport->encoded_outgoing))
                {
                  _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
                  oom = TRUE;
                  goto out;
                }
            }
          
          total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);

#if 0
          _dbus_verbose ("encoded message is %d bytes\n",
                         total_bytes_to_write);
#endif
          
          bytes_written =
            _dbus_write_socket (socket_transport->fd,
                                &socket_transport->encoded_outgoing,
                                socket_transport->message_bytes_written,
                                total_bytes_to_write - socket_transport->message_bytes_written);
        }
      else
        {
          total_bytes_to_write = header_len + body_len;

#if 0
          _dbus_verbose ("message is %d bytes\n",
                         total_bytes_to_write);
#endif

#ifdef HAVE_UNIX_FD_PASSING
          if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
            {
              /* Send the fds along with the first byte of the message */
              const int *unix_fds;
              unsigned n;

              _dbus_message_get_unix_fds(message, &unix_fds, &n);

              bytes_written =
                _dbus_write_socket_with_unix_fds_two (socket_transport->fd,
                                                      header,
                                                      socket_transport->message_bytes_written,
                                                      header_len - socket_transport->message_bytes_written,
                                                      body,
                                                      0, body_len,
                                                      unix_fds,
                                                      n);

              if (bytes_written > 0 && n > 0)
                _dbus_verbose("Wrote %i unix fds\n", n);
            }
          else
#endif
            {
              if (socket_transport->message_bytes_written < header_len)
                {
                  bytes_written =
                    _dbus_write_socket_two (socket_transport->fd,
                                            header,
                                            socket_transport->message_bytes_written,
                                            header_len - socket_transport->message_bytes_written,
                                            body,
                                            0, body_len);
                }
              else
                {
                  bytes_written =
                    _dbus_write_socket (socket_transport->fd,
                                        body,
                                        (socket_transport->message_bytes_written - header_len),
                                        body_len -
                                        (socket_transport->message_bytes_written - header_len));
                }
            }
        }

      if (bytes_written < 0)
        {
          /* EINTR already handled for us */
          
          /* For some discussion of why we also ignore EPIPE here, see
           * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
           */
          
          if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ())
            goto out;
          else
            {
              _dbus_verbose ("Error writing to remote app: %s\n",
                             _dbus_strerror_from_errno ());
              do_io_error (transport);
              goto out;
            }
        }
      else
        {
          _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
                         total_bytes_to_write);
          
          total += bytes_written;
          socket_transport->message_bytes_written += bytes_written;

          _dbus_assert (socket_transport->message_bytes_written <=
                        total_bytes_to_write);
          
          if (socket_transport->message_bytes_written == total_bytes_to_write)
            {
              socket_transport->message_bytes_written = 0;
              _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
              _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);

              _dbus_connection_message_sent_unlocked (transport->connection,
                                                      message);
            }
        }
    }

 out:
  if (oom)
    return FALSE;
  else
    return TRUE;
}
Ejemplo n.º 24
0
/* returns false on oom */
static dbus_bool_t
do_writing (DBusTransport *transport)
{
  int total;
  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
  dbus_bool_t oom;
  
  /* No messages without authentication! */
  if (!_dbus_transport_try_to_authenticate (transport))
    {
      _dbus_verbose ("Not authenticated, not writing anything\n");
      return TRUE;
    }

  if (transport->disconnected)
    {
      _dbus_verbose ("Not connected, not writing anything\n");
      return TRUE;
    }

#if 1
  _dbus_verbose ("do_writing(), have_messages = %d, fd = %" DBUS_SOCKET_FORMAT "\n",
                 _dbus_connection_has_messages_to_send_unlocked (transport->connection),
                 _dbus_socket_printable (socket_transport->fd));
#endif
  
  oom = FALSE;
  total = 0;

  while (!transport->disconnected &&
         _dbus_connection_has_messages_to_send_unlocked (transport->connection))
    {
      int bytes_written;
      DBusMessage *message;
      const DBusString *header;
      const DBusString *body;
      int header_len, body_len;
      int total_bytes_to_write;
      int saved_errno;
      
      if (total > socket_transport->max_bytes_written_per_iteration)
        {
          _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
                         total, socket_transport->max_bytes_written_per_iteration);
          goto out;
        }
      
      message = _dbus_connection_get_message_to_send (transport->connection);
      _dbus_assert (message != NULL);
      dbus_message_lock (message);

#if 0
      _dbus_verbose ("writing message %p\n", message);
#endif
      
      _dbus_message_get_network_data (message,
                                      &header, &body);

      header_len = _dbus_string_get_length (header);
      body_len = _dbus_string_get_length (body);

      if (_dbus_auth_needs_encoding (transport->auth))
        {
          /* Does fd passing even make sense with encoded data? */
          _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));

          if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
            {
              if (!_dbus_auth_encode_data (transport->auth,
                                           header, &socket_transport->encoded_outgoing))
                {
                  oom = TRUE;
                  goto out;
                }
              
              if (!_dbus_auth_encode_data (transport->auth,
                                           body, &socket_transport->encoded_outgoing))
                {
                  _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
                  oom = TRUE;
                  goto out;
                }
            }
          
          total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);

#if 0
          _dbus_verbose ("encoded message is %d bytes\n",
                         total_bytes_to_write);
#endif
          
          bytes_written =
            _dbus_write_socket (socket_transport->fd,
                                &socket_transport->encoded_outgoing,
                                socket_transport->message_bytes_written,
                                total_bytes_to_write - socket_transport->message_bytes_written);
          saved_errno = _dbus_save_socket_errno ();
        }
      else
        {
          total_bytes_to_write = header_len + body_len;

#if 0
          _dbus_verbose ("message is %d bytes\n",
                         total_bytes_to_write);
#endif

#ifdef HAVE_UNIX_FD_PASSING
          if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
            {
              /* Send the fds along with the first byte of the message */
              const int *unix_fds;
              unsigned n;

              _dbus_message_get_unix_fds(message, &unix_fds, &n);

              bytes_written =
                _dbus_write_socket_with_unix_fds_two (socket_transport->fd,
                                                      header,
                                                      socket_transport->message_bytes_written,
                                                      header_len - socket_transport->message_bytes_written,
                                                      body,
                                                      0, body_len,
                                                      unix_fds,
                                                      n);
              saved_errno = _dbus_save_socket_errno ();

              if (bytes_written > 0 && n > 0)
                _dbus_verbose("Wrote %i unix fds\n", n);
            }
          else
#endif
            {
              if (socket_transport->message_bytes_written < header_len)
                {
                  bytes_written =
                    _dbus_write_socket_two (socket_transport->fd,
                                            header,
                                            socket_transport->message_bytes_written,
                                            header_len - socket_transport->message_bytes_written,
                                            body,
                                            0, body_len);
                }
              else
                {
                  bytes_written =
                    _dbus_write_socket (socket_transport->fd,
                                        body,
                                        (socket_transport->message_bytes_written - header_len),
                                        body_len -
                                        (socket_transport->message_bytes_written - header_len));
                }

              saved_errno = _dbus_save_socket_errno ();
            }
        }

      if (bytes_written < 0)
        {
          /* EINTR already handled for us */
          
          /* If the other end closed the socket with close() or shutdown(), we
           * receive EPIPE here but we must not close the socket yet: there
           * might still be some data to read. See:
           * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
           */
          
          if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno) || _dbus_get_is_errno_epipe (saved_errno))
            goto out;

          /* Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg()
           * on Unix sockets returns -1 errno=ETOOMANYREFS when the passfd
           * mechanism (SCM_RIGHTS) is used recursively with a recursion level
           * of maximum 4. The kernel does not have an API to check whether
           * the passed fds can be forwarded and it can change asynchronously.
           * See:
           * https://bugs.freedesktop.org/show_bug.cgi?id=80163
           */

          else if (_dbus_get_is_errno_etoomanyrefs (saved_errno))
            {
              /* We only send fds in the first byte of the message.
               * ETOOMANYREFS cannot happen after.
               */
              _dbus_assert (socket_transport->message_bytes_written == 0);

              _dbus_verbose (" discard message of %d bytes due to ETOOMANYREFS\n",
                             total_bytes_to_write);

              socket_transport->message_bytes_written = 0;
              _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
              _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);

              /* The message was not actually sent but it needs to be removed
               * from the outgoing queue
               */
              _dbus_connection_message_sent_unlocked (transport->connection,
                                                      message);
            }
          else
            {
              _dbus_verbose ("Error writing to remote app: %s\n",
                             _dbus_strerror (saved_errno));
              do_io_error (transport);
              goto out;
            }
        }
      else
        {
          _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
                         total_bytes_to_write);
          
          total += bytes_written;
          socket_transport->message_bytes_written += bytes_written;

          _dbus_assert (socket_transport->message_bytes_written <=
                        total_bytes_to_write);
          
          if (socket_transport->message_bytes_written == total_bytes_to_write)
            {
              socket_transport->message_bytes_written = 0;
              _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
              _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);

              _dbus_connection_message_sent_unlocked (transport->connection,
                                                      message);
            }
        }
    }

 out:
  if (oom)
    return FALSE;
  else
    return TRUE;
}
Ejemplo n.º 25
0
static BusDesktopFile *
desktop_file_for_name (BusConfigParser *parser,
                       const char *name,
                       DBusError  *error)
{
  BusDesktopFile *desktop_file;
  DBusList **service_dirs;
  DBusList *link;
  DBusError tmp_error;
  DBusString full_path;
  DBusString filename;
  const char *dir;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  desktop_file = NULL;

  if (!_dbus_string_init (&filename))
    {
      BUS_SET_OOM (error);
      goto out_all;
    }

  if (!_dbus_string_init (&full_path))
    {
      BUS_SET_OOM (error);
      goto out_filename;
    }

  if (!_dbus_string_append (&filename, name) ||
      !_dbus_string_append (&filename, ".service"))
    {
      BUS_SET_OOM (error);
      goto out;
    }

  service_dirs = bus_config_parser_get_service_dirs (parser);
  for (link = _dbus_list_get_first_link (service_dirs);
       link != NULL;
       link = _dbus_list_get_next_link (service_dirs, link))
    {
      dir = link->data;
      _dbus_verbose ("Looking at '%s'\n", dir);

      dbus_error_init (&tmp_error);

      /* clear the path from last time */
      _dbus_string_set_length (&full_path, 0);

      /* build the full path */
      if (!_dbus_string_append (&full_path, dir) ||
          !_dbus_concat_dir_and_file (&full_path, &filename))
        {
          BUS_SET_OOM (error);
          goto out;
        }

      _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path));
      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
      if (desktop_file == NULL)
        {
          _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
          _dbus_verbose ("Could not load %s: %s: %s\n",
                         _dbus_string_get_const_data (&full_path),
                         tmp_error.name, tmp_error.message);

          /* we may have failed if the file is not found; this is not fatal */
          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
            {
              dbus_move_error (&tmp_error, error);
              /* we only bail out on OOM */
              goto out;
            }
          dbus_error_free (&tmp_error);
        }

      /* did we find the desktop file we want? */
      if (desktop_file != NULL)
        break;
    }

  /* Didn't find desktop file; set error */
  if (desktop_file == NULL)
    {
      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
                      "The name %s was not provided by any .service files",
                      name);
    }

out:
  _dbus_string_free (&full_path);
out_filename:
  _dbus_string_free (&filename);
out_all:
  return desktop_file;
}
Ejemplo n.º 26
0
/**
 * Appends the contents of the given file to the string,
 * returning error code. At the moment, won't open a file
 * more than a megabyte in size.
 *
 * @param str the string to append to
 * @param filename filename to load
 * @param error place to set an error
 * @returns #FALSE if error was set
 */
dbus_bool_t
_dbus_file_get_contents (DBusString       *str,
                         const DBusString *filename,
                         DBusError        *error)
{
  HANDLE hnd;
  DWORD fsize;
  DWORD fsize_hi;
  int orig_len;
  unsigned int total;
  const char *filename_c;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  filename_c = _dbus_string_get_const_data (filename);

  hnd = CreateFileA (filename_c, GENERIC_READ,
                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hnd == INVALID_HANDLE_VALUE)
    {
      char *emsg = _dbus_win_error_string (GetLastError ());
      dbus_set_error (error, _dbus_win_error_from_last_error (),
                       "Failed to open \"%s\": %s", filename_c, emsg);
      _dbus_win_free_error_string (emsg);
      return FALSE;
    }

  _dbus_verbose ("file %s hnd %p opened\n", filename_c, hnd);
  
  fsize = GetFileSize (hnd, &fsize_hi);
  if (fsize == 0xFFFFFFFF && GetLastError() != NO_ERROR)
    { 
      char *emsg = _dbus_win_error_string (GetLastError ());
      dbus_set_error (error, _dbus_win_error_from_last_error (),
                      "Failed to get file size for \"%s\": %s",
                      filename_c, emsg);
      _dbus_win_free_error_string (emsg);

      _dbus_verbose ("GetFileSize() failed: %s", emsg);

      CloseHandle (hnd);

      return FALSE;
    }

  if (fsize_hi != 0 || fsize > _DBUS_ONE_MEGABYTE)
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "File size %lu/%lu of \"%s\" is too large.",
                      (unsigned long) fsize_hi,
                      (unsigned long) fsize, filename_c);
      CloseHandle (hnd);
      return FALSE;
    }

  total = 0;
  orig_len = _dbus_string_get_length (str);
  if (fsize > 0)
    {
      int bytes_read;

      while (total < fsize)
        {
          bytes_read = _dbus_file_read (hnd, str, fsize - total, error);
          if (bytes_read <= 0)
            {
              if (bytes_read == 0)
                {
                  dbus_set_error (error, DBUS_ERROR_FAILED,
                                  "Premature EOF reading \"%s\"",
                                  filename_c);
                }
              else
                _DBUS_ASSERT_ERROR_IS_SET (error);

              CloseHandle (hnd);
              _dbus_string_set_length (str, orig_len);
              return FALSE;
            }
          else
            total += bytes_read;
        }

      CloseHandle (hnd);
      return TRUE;
    }
  else
    {
      CloseHandle (hnd);
      return TRUE;
    }
}
Ejemplo n.º 27
0
int
main (int    argc,
      char **argv)
{
  const char *test_data_dir;
  const char *failure_dir_c;
  int total_failures_found;
  
  if (argc > 1)
    test_data_dir = argv[1];
  else
    {
      fprintf (stderr, "Must specify a top_srcdir/test/data directory\n");
      return 1;
    }

  total_failures_found = 0;
  total_attempts = 0;

  if (!_dbus_string_init (&failure_dir))
    return 1;

  /* so you can leave it overnight safely */
#define MAX_FAILURES 1000

  while (total_failures_found < MAX_FAILURES)
    {
      unsigned int seed;

      failures_this_iteration = 0;

      seed = get_random_seed ();

      _dbus_string_set_length (&failure_dir, 0);

      if (!_dbus_string_append (&failure_dir, "failures-"))
        return 1;

      if (!_dbus_string_append_uint (&failure_dir, seed))
        return 1;

      failure_dir_c = _dbus_string_get_const_data (&failure_dir);

      if (mkdir (failure_dir_c, 0700) < 0)
        {
          if (errno != EEXIST)
            fprintf (stderr, "didn't mkdir %s: %s\n",
                     failure_dir_c, strerror (errno));
        }

      printf ("next seed = %u \ttotal failures %d of %d attempts\n",
              seed, total_failures_found, total_attempts);

      srand (seed);

      if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
                                                          find_breaks_based_on,
                                                          NULL))
        {
          fprintf (stderr, "fatal error iterating over message files\n");
          rmdir (failure_dir_c);
          return 1;
        }

      printf ("  did %d random mutations: %d %d %d %d %d %d %d\n",
              _DBUS_N_ELEMENTS (times_we_did_each_thing),
              times_we_did_each_thing[0],
              times_we_did_each_thing[1],
              times_we_did_each_thing[2],
              times_we_did_each_thing[3],
              times_we_did_each_thing[4],
              times_we_did_each_thing[5],
              times_we_did_each_thing[6]);
      
      printf ("Found %d failures with seed %u stored in %s\n",
              failures_this_iteration, seed, failure_dir_c);

      total_failures_found += failures_this_iteration;

      rmdir (failure_dir_c); /* does nothing if non-empty */
    }

  return 0;
}
Ejemplo n.º 28
0
/* returns false on out-of-memory */
static dbus_bool_t
do_reading (DBusTransport *transport)
{
  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
  DBusString *buffer;
  int bytes_read;
  int total;
  dbus_bool_t oom;
  int saved_errno;

  _dbus_verbose ("fd = %" DBUS_SOCKET_FORMAT "\n",
                 _dbus_socket_printable (socket_transport->fd));
  
  /* No messages without authentication! */
  if (!_dbus_transport_try_to_authenticate (transport))
    return TRUE;

  oom = FALSE;
  
  total = 0;

 again:
  
  /* See if we've exceeded max messages and need to disable reading */
  check_read_watch (transport);
  
  if (total > socket_transport->max_bytes_read_per_iteration)
    {
      _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
                     total, socket_transport->max_bytes_read_per_iteration);
      goto out;
    }

  _dbus_assert (socket_transport->read_watch != NULL ||
                transport->disconnected);
  
  if (transport->disconnected)
    goto out;

  if (!dbus_watch_get_enabled (socket_transport->read_watch))
    return TRUE;
  
  if (_dbus_auth_needs_decoding (transport->auth))
    {
      /* Does fd passing even make sense with encoded data? */
      _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));

      if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
        bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
      else
        bytes_read = _dbus_read_socket (socket_transport->fd,
                                        &socket_transport->encoded_incoming,
                                        socket_transport->max_bytes_read_per_iteration);

      saved_errno = _dbus_save_socket_errno ();

      _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
                    bytes_read);
      
      if (bytes_read > 0)
        {
          _dbus_message_loader_get_buffer (transport->loader,
                                           &buffer);

          if (!_dbus_auth_decode_data (transport->auth,
                                       &socket_transport->encoded_incoming,
                                       buffer))
            {
              _dbus_verbose ("Out of memory decoding incoming data\n");
              _dbus_message_loader_return_buffer (transport->loader,
                                              buffer);

              oom = TRUE;
              goto out;
            }

          _dbus_message_loader_return_buffer (transport->loader,
                                              buffer);

          _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
          _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
        }
    }
  else
    {
      _dbus_message_loader_get_buffer (transport->loader,
                                       &buffer);

#ifdef HAVE_UNIX_FD_PASSING
      if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
        {
          int *fds;
          unsigned int n_fds;

          if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
            {
              _dbus_verbose ("Out of memory reading file descriptors\n");
              _dbus_message_loader_return_buffer (transport->loader, buffer);
              oom = TRUE;
              goto out;
            }

          bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
                                                       buffer,
                                                       socket_transport->max_bytes_read_per_iteration,
                                                       fds, &n_fds);
          saved_errno = _dbus_save_socket_errno ();

          if (bytes_read >= 0 && n_fds > 0)
            _dbus_verbose("Read %i unix fds\n", n_fds);

          _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
        }
      else
#endif
        {
          bytes_read = _dbus_read_socket (socket_transport->fd,
                                          buffer, socket_transport->max_bytes_read_per_iteration);
          saved_errno = _dbus_save_socket_errno ();
        }

      _dbus_message_loader_return_buffer (transport->loader,
                                          buffer);
    }

  if (bytes_read < 0)
    {
      /* EINTR already handled for us */

      if (_dbus_get_is_errno_enomem (saved_errno))
        {
          _dbus_verbose ("Out of memory in read()/do_reading()\n");
          oom = TRUE;
          goto out;
        }
      else if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
        goto out;
      else
        {
          _dbus_verbose ("Error reading from remote app: %s\n",
                         _dbus_strerror (saved_errno));
          do_io_error (transport);
          goto out;
        }
    }
  else if (bytes_read == 0)
    {
      _dbus_verbose ("Disconnected from remote app\n");
      do_io_error (transport);
      goto out;
    }
  else
    {
      _dbus_verbose (" read %d bytes\n", bytes_read);
      
      total += bytes_read;      

      if (!_dbus_transport_queue_messages (transport))
        {
          oom = TRUE;
          _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
          goto out;
        }
      
      /* Try reading more data until we get EAGAIN and return, or
       * exceed max bytes per iteration.  If in blocking mode of
       * course we'll block instead of returning.
       */
      goto again;
    }

 out:
  if (oom)
    return FALSE;
  else
    return TRUE;
}
Ejemplo n.º 29
0
/**
 * Check if Apparmor security controls allow the message to be sent to a
 * particular connection based on the security context of the sender and
 * that of the receiver. The destination connection need not be the
 * addressed recipient, it could be an "eavesdropper"
 *
 * @param sender the sender of the message.
 * @param proposed_recipient the connection the message is to be sent to.
 * @param requested_reply TRUE if the message is a reply requested by
 *                        proposed_recipient
 * @param bustype name of the bus
 * @param msgtype message type (DBUS_MESSAGE_TYPE_METHOD_CALL, etc.)
 * @param path object path the message should be sent to
 * @param interface the type of the object instance
 * @param member the member of the object
 * @param error_name the name of the error if the message type is error
 * @param destination name that the message should be sent to
 * @param source name that the message should be sent from
 * @param error the reason for failure when FALSE is returned
 * @returns TRUE if the message is permitted
 */
dbus_bool_t
bus_apparmor_allows_send (DBusConnection     *sender,
                          DBusConnection     *proposed_recipient,
                          dbus_bool_t         requested_reply,
                          const char         *bustype,
                          int                 msgtype,
                          const char         *path,
                          const char         *interface,
                          const char         *member,
                          const char         *error_name,
                          const char         *destination,
                          const char         *source,
                          BusActivationEntry *activation_entry,
                          DBusError          *error)
{
#ifdef HAVE_APPARMOR
  BusAppArmorConfinement *src_con = NULL, *dst_con = NULL;
  DBusString qstr, auxdata;
  int src_allow = FALSE, dst_allow = FALSE;
  int src_audit = TRUE, dst_audit = TRUE;
  dbus_bool_t free_auxdata = FALSE;
  unsigned long pid;
  int len, res, src_errno = 0, dst_errno = 0;
  uint32_t src_perm = AA_DBUS_SEND, dst_perm = AA_DBUS_RECEIVE;
  const char *msgtypestr = dbus_message_type_to_string(msgtype);
  const char *dst_label = NULL;
  const char *dst_mode = NULL;

  if (!apparmor_enabled)
    return TRUE;

  _dbus_assert (sender != NULL);

  src_con = bus_connection_dup_apparmor_confinement (sender);

  if (proposed_recipient)
    {
      dst_con = bus_connection_dup_apparmor_confinement (proposed_recipient);
    }
  else if (activation_entry != NULL)
    {
      dst_label = bus_activation_entry_get_assumed_apparmor_label (activation_entry);
    }
  else
    {
      dst_con = bus_con;
      bus_apparmor_confinement_ref (dst_con);
    }

  if (dst_con != NULL)
    {
      dst_label = dst_con->label;
      dst_mode = dst_con->mode;
    }

  /* map reply messages to initial send and receive permission. That is
   * permission to receive a message from X grants permission to reply to X.
   * And permission to send a message to Y grants permission to receive a reply
   * from Y. Note that this only applies to requested replies. Unrequested
   * replies still require a policy query.
   */
  if (requested_reply)
    {
      /* ignore requested reply messages and let dbus reply mapping handle them
       * as the send was already allowed
       */
      src_allow = TRUE;
      dst_allow = TRUE;
      goto out;
    }

  if (is_unconfined (src_con->label, src_con->mode))
    {
      src_allow = TRUE;
      src_audit = FALSE;
    }
  else
    {
      if (!_dbus_string_init (&qstr))
        goto oom;

      if (!build_message_query (&qstr, src_con->label, bustype, destination,
                                dst_label, path, interface, member))
        {
          _dbus_string_free (&qstr);
          goto oom;
        }

      res = aa_query_label (src_perm,
                            _dbus_string_get_data (&qstr),
                            _dbus_string_get_length (&qstr),
                            &src_allow, &src_audit);
      _dbus_string_free (&qstr);
      if (res == -1)
        {
          src_errno = errno;
          set_error_from_query_errno (error, src_errno);
          goto audit;
        }
    }

  /* When deciding whether we can activate a service, we only check that
   * we are allowed to send a message to it, not that it is allowed to
   * receive that message from us.
   */
  if (activation_entry != NULL || is_unconfined (dst_label, dst_mode))
    {
      dst_allow = TRUE;
      dst_audit = FALSE;
    }
  else
    {
      if (!_dbus_string_init (&qstr))
        goto oom;

      if (!build_message_query (&qstr, dst_label, bustype, source,
                                src_con->label, path, interface, member))
        {
          _dbus_string_free (&qstr);
          goto oom;
        }

      res = aa_query_label (dst_perm,
                            _dbus_string_get_data (&qstr),
                            _dbus_string_get_length (&qstr),
                            &dst_allow, &dst_audit);
      _dbus_string_free (&qstr);
      if (res == -1)
        {
          dst_errno = errno;
          set_error_from_query_errno (error, dst_errno);
          goto audit;
        }
    }

  /* Don't fail operations on profiles in complain mode */
  if (modestr_is_complain (src_con->mode))
    src_allow = TRUE;
  if (modestr_is_complain (dst_mode))
    dst_allow = TRUE;

  if (!src_allow || !dst_allow)
    set_error_from_denied_message (error,
                                   sender,
                                   proposed_recipient,
                                   requested_reply,
                                   msgtypestr,
                                   path,
                                   interface,
                                   member,
                                   error_name,
                                   destination);

  /* Don't audit the message if one of the following conditions is true:
   *   1) The AppArmor query indicates that auditing should not happen.
   *   2) The message is a reply type. Reply message are not audited because
   *      the AppArmor policy language does not have the notion of a reply
   *      message. Unrequested replies will be silently discarded if the sender
   *      does not have permission to send to the receiver or if the receiver
   *      does not have permission to receive from the sender.
   */
  if ((!src_audit && !dst_audit) ||
      (msgtype == DBUS_MESSAGE_TYPE_METHOD_RETURN ||
       msgtype == DBUS_MESSAGE_TYPE_ERROR))
    goto out;

 audit:
  if (!_dbus_string_init (&auxdata))
    goto oom;
  free_auxdata = TRUE;

  if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown"))
    goto oom;

  if (path && !_dbus_append_pair_str (&auxdata, "path", path))
    goto oom;

  if (interface && !_dbus_append_pair_str (&auxdata, "interface", interface))
    goto oom;

  if (member && !_dbus_append_pair_str (&auxdata, "member", member))
    goto oom;

  if (error_name && !_dbus_append_pair_str (&auxdata, "error_name", error_name))
    goto oom;

  len = _dbus_string_get_length (&auxdata);

  if (src_audit)
    {
      if (!_dbus_append_mask (&auxdata, src_perm))
        goto oom;

      if (destination && !_dbus_append_pair_str (&auxdata, "name", destination))
        goto oom;

      if (sender && dbus_connection_get_unix_process_id (sender, &pid) &&
          !_dbus_append_pair_uint (&auxdata, "pid", pid))
        goto oom;

      if (src_con->label &&
          !_dbus_append_pair_str (&auxdata, "label", src_con->label))
        goto oom;

      if (proposed_recipient &&
          dbus_connection_get_unix_process_id (proposed_recipient, &pid) &&
          !_dbus_append_pair_uint (&auxdata, "peer_pid", pid))
        goto oom;

      if (dst_label &&
          !_dbus_append_pair_str (&auxdata, "peer_label", dst_label))
        goto oom;

      if (src_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (src_errno)))
        goto oom;

      if (dst_errno &&
          !_dbus_append_pair_str (&auxdata, "peer_info", strerror (dst_errno)))
        goto oom;

      log_message (src_allow, msgtypestr, &auxdata);
    }
  if (dst_audit)
    {
      _dbus_string_set_length (&auxdata, len);

      if (source && !_dbus_append_pair_str (&auxdata, "name", source))
        goto oom;

      if (!_dbus_append_mask (&auxdata, dst_perm))
        goto oom;

      if (proposed_recipient &&
          dbus_connection_get_unix_process_id (proposed_recipient, &pid) &&
          !_dbus_append_pair_uint (&auxdata, "pid", pid))
        goto oom;

      if (dst_label &&
          !_dbus_append_pair_str (&auxdata, "label", dst_label))
        goto oom;

      if (sender && dbus_connection_get_unix_process_id (sender, &pid) &&
          !_dbus_append_pair_uint (&auxdata, "peer_pid", pid))
        goto oom;

      if (src_con->label &&
          !_dbus_append_pair_str (&auxdata, "peer_label", src_con->label))
        goto oom;

      if (dst_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (dst_errno)))
        goto oom;

      if (src_errno &&
          !_dbus_append_pair_str (&auxdata, "peer_info", strerror (src_errno)))
        goto oom;

      log_message (dst_allow, msgtypestr, &auxdata);
    }

 out:
  if (src_con != NULL)
    bus_apparmor_confinement_unref (src_con);
  if (dst_con != NULL)
    bus_apparmor_confinement_unref (dst_con);
  if (free_auxdata)
    _dbus_string_free (&auxdata);

  return src_allow && dst_allow;

 oom:
  if (error != NULL && !dbus_error_is_set (error))
    BUS_SET_OOM (error);
  src_allow = FALSE;
  dst_allow = FALSE;
  goto out;

#else
  return TRUE;
#endif /* HAVE_APPARMOR */
}