Ejemplo n.º 1
0
void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address)
{
	void *x;

	FLAC__ASSERT(0 != aligned_address);

#ifdef FLAC__ALIGN_MALLOC_DATA
	/* align on 32-byte (256-bit) boundary */
	x = safe_malloc_add_2op_(bytes, /*+*/31);
#ifdef SIZEOF_VOIDP
#if SIZEOF_VOIDP == 4
		/* could do  *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */
		*aligned_address = (void*)(((unsigned)x + 31) & -32);
#elif SIZEOF_VOIDP == 8
		*aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32)));
#else
# error  Unsupported sizeof(void*)
#endif
#else
	/* there's got to be a better way to do this right for all archs */
	if(sizeof(void*) == sizeof(unsigned))
		*aligned_address = (void*)(((unsigned)x + 31) & -32);
	else if(sizeof(void*) == sizeof(FLAC__uint64))
		*aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32)));
	else
		return 0;
#endif
#else
	x = safe_malloc_(bytes);
	*aligned_address = x;
#endif
	return x;
}
Ejemplo n.º 2
0
void *safe_malloc_add_2op_(size_t size1, size_t size2) {
  size_t size = size1 + size2;
  if (size < size1)
    return NULL;

  return safe_malloc_(size);
}
Ejemplo n.º 3
0
void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address)
{
	void *x;

	FLAC__ASSERT(0 != aligned_address);

#ifdef FLAC__ALIGN_MALLOC_DATA
	/* align on 32-byte (256-bit) boundary */
	x = safe_malloc_add_2op_(bytes, /*+*/31L);
	*aligned_address = (void*)(((uintptr_t)x + 31L) & -32L);
#else
	x = safe_malloc_(bytes);
	*aligned_address = x;
#endif
	return x;
}
Ejemplo n.º 4
0
FLAC__bool simple_ogg_page__get_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderReadCallback read_callback, void *client_data)
{
	static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27;
	static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255;
	FLAC__byte crc[4];
	FLAC__StreamEncoderSeekStatus seek_status;

	FLAC__ASSERT(page->header == 0);
	FLAC__ASSERT(page->header_len == 0);
	FLAC__ASSERT(page->body == 0);
	FLAC__ASSERT(page->body_len == 0);

	/* move the stream pointer to the supposed beginning of the page */
	if(0 == seek_callback)
		return false;
	if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
		if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
			encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
		return false;
	}

	/* allocate space for the page header */
	if(0 == (page->header = safe_malloc_(OGG_MAX_HEADER_LEN))) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
		return false;
	}

	/* read in the fixed part of the page header (up to but not including
	 * the segment table */
	if(!full_read_(encoder, page->header, OGG_HEADER_FIXED_PORTION_LEN, read_callback, client_data))
		return false;

	page->header_len = OGG_HEADER_FIXED_PORTION_LEN + page->header[26];

	/* check to see if it's a correct, "simple" page (one packet only) */
	if(
		memcmp(page->header, "OggS", 4) ||               /* doesn't start with OggS */
		(page->header[5] & 0x01) ||                      /* continued packet */
		memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */
		page->header[26] == 0                            /* packet is 0-size */
	) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
		return false;
	}

	/* read in the segment table */
	if(!full_read_(encoder, page->header + OGG_HEADER_FIXED_PORTION_LEN, page->header[26], read_callback, client_data))
		return false;

	{
		unsigned i;

		/* check to see that it specifies a single packet */
		for(i = 0; i < (unsigned)page->header[26] - 1; i++) {
			if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) {
				encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
				return false;
			}
		}

		page->body_len = 255 * i + page->header[i + OGG_HEADER_FIXED_PORTION_LEN];
	}

	/* allocate space for the page body */
	if(0 == (page->body = safe_malloc_(page->body_len))) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
		return false;
	}

	/* read in the page body */
	if(!full_read_(encoder, page->body, page->body_len, read_callback, client_data))
		return false;

	/* check the CRC */
	memcpy(crc, page->header+22, 4);
	ogg_page_checksum_set(page);
	if(memcmp(crc, page->header+22, 4)) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
		return false;
	}

	return true;
}
Ejemplo n.º 5
0
FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, const char **error_message)
{
	FLAC__StreamMetadata *obj;
	int state = 0;
	static const char *error_messages[] = {
		"memory allocation error",
		"invalid picture specification",
		"invalid picture specification: can't parse resolution/color part",
		"unable to extract resolution and color info from URL, user must set explicitly",
		"unable to extract resolution and color info from file, user must set explicitly",
		"error opening picture file",
		"error reading picture file",
		"invalid picture type",
		"unable to guess MIME type from file, user must set explicitly",
		"type 1 icon must be a 32x32 pixel PNG"
	};

	FLAC__ASSERT(0 != spec);
	FLAC__ASSERT(0 != error_message);

	/* double protection */
	if(0 == spec)
		return 0;
	if(0 == error_message)
		return 0;

	*error_message = 0;

	if(0 == (obj = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE))) {
		*error_message = error_messages[0];
		return obj;
	}

	if(strchr(spec, '|')) { /* full format */
		const char *p;
		char *q;
		for(p = spec; *error_message==0 && *p; ) {
			if(*p == '|') {
				switch(state) {
					case 0: /* type */
						if(!local__parse_type_(spec, p-spec, &obj->data.picture))
							*error_message = error_messages[7];
						break;
					case 1: /* mime type */
						if(p-spec) { /* if blank, we'll try to guess later from the picture data */
							if(0 == (q = local__strndup_(spec, p-spec)))
								*error_message = error_messages[0];
							else if(!FLAC__metadata_object_picture_set_mime_type(obj, q, /*copy=*/false))
								*error_message = error_messages[0];
						}
						break;
					case 2: /* description */
						if(0 == (q = local__strndup_(spec, p-spec)))
							*error_message = error_messages[0];
						else if(!FLAC__metadata_object_picture_set_description(obj, (FLAC__byte*)q, /*copy=*/false))
							*error_message = error_messages[0];
						break;
					case 3: /* resolution/color (e.g. [300x300x16[/1234]] */
						if(!local__parse_resolution_(spec, p-spec, &obj->data.picture))
							*error_message = error_messages[2];
						break;
					default:
						*error_message = error_messages[1];
						break;
				}
				p++;
				spec = p;
				state++;
			}
			else
				p++;
		}
	}
	else { /* simple format, filename only, everything else guessed */
		if(!local__parse_type_("", 0, &obj->data.picture)) /* use default picture type */
			*error_message = error_messages[7];
		/* leave MIME type to be filled in later */
		/* leave description empty */
		/* leave the rest to be filled in later: */
		else if(!local__parse_resolution_("", 0, &obj->data.picture))
			*error_message = error_messages[2];
		else
			state = 4;
	}

	/* parse filename, read file, try to extract resolution/color info if needed */
	if(*error_message == 0) {
		if(state != 4)
			*error_message = error_messages[1];
		else { /* 'spec' points to filename/URL */
			if(0 == strcmp(obj->data.picture.mime_type, "-->")) { /* magic MIME type means URL */
				if(!FLAC__metadata_object_picture_set_data(obj, (FLAC__byte*)spec, strlen(spec), /*copy=*/true))
					*error_message = error_messages[0];
				else if(obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0)
					*error_message = error_messages[3];
			}
			else { /* regular picture file */
				const FLAC__off_t size = grabbag__file_get_filesize(spec);
				if(size < 0)
					*error_message = error_messages[5];
				else {
					FLAC__byte *buffer = safe_malloc_(size);
					if(0 == buffer)
						*error_message = error_messages[0];
					else {
						FILE *f = flac_fopen(spec, "rb");
						if(0 == f) {
							*error_message = error_messages[5];
							free(buffer);
						}
						else {
							if(fread(buffer, 1, size, f) != (size_t)size)
								*error_message = error_messages[6];
							fclose(f);
							if(0 == *error_message) {
								if(!FLAC__metadata_object_picture_set_data(obj, buffer, size, /*copy=*/false))
									*error_message = error_messages[6];
								/* try to extract MIME type if user left it blank */
								else if(*obj->data.picture.mime_type == '\0' && !local__extract_mime_type_(obj))
									*error_message = error_messages[8];
								/* try to extract resolution/color info if user left it blank */
								else if((obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) && !local__extract_resolution_color_info_(&obj->data.picture))
									*error_message = error_messages[4];
							}
							else {
								free(buffer);
							}
						}
					}
				}
			}
		}
	}

	if(*error_message == 0) {
		if(
			obj->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD &&
			(
				(strcmp(obj->data.picture.mime_type, "image/png") && strcmp(obj->data.picture.mime_type, "-->")) ||
				obj->data.picture.width != 32 ||
				obj->data.picture.height != 32
			)
		)
			*error_message = error_messages[9];
	}

	if(*error_message && obj) {
		FLAC__metadata_object_delete(obj);
		obj = 0;
	}

	return obj;
}
Ejemplo n.º 6
0
int iconvert(const char *fromcode, const char *tocode,
	     const char *from, size_t fromlen,
	     char **to, size_t *tolen)
{
  int ret = 0;
  iconv_t cd1, cd2;
  char *ib;
  char *ob;
  char *utfbuf = 0, *outbuf, *newbuf;
  size_t utflen, outlen, ibl, obl, k;
  char tbuf[2048];

  cd1 = iconv_open("UTF-8", fromcode);
  if (cd1 == (iconv_t)(-1))
    return -1;

  cd2 = (iconv_t)(-1);
  /* Don't use strcasecmp() as it's locale-dependent. */
  if (!strchr("Uu", tocode[0]) ||
      !strchr("Tt", tocode[1]) ||
      !strchr("Ff", tocode[2]) ||
      tocode[3] != '-' ||
      tocode[4] != '8' ||
      tocode[5] != '\0') {
    char *tocode1;
	size_t dest_len = strlen(tocode) + 11;
    /*
     * Try using this non-standard feature of glibc and libiconv.
     * This is deliberately not a config option as people often
     * change their iconv library without rebuilding applications.
     */
    tocode1 = safe_malloc_(dest_len);
    if (!tocode1)
      goto fail;

    safe_strncpy(tocode1, tocode, dest_len);
    safe_strncat(tocode1, "//TRANSLIT", dest_len);
    cd2 = iconv_open(tocode1, "UTF-8");
    free(tocode1);

    if (cd2 == (iconv_t)(-1))
      cd2 = iconv_open(tocode, fromcode);

    if (cd2 == (iconv_t)(-1)) {
      iconv_close(cd1);
      return -1;
    }
  }

  utflen = 1; /*fromlen * 2 + 1; XXX */
  utfbuf = malloc(utflen);
  if (!utfbuf)
    goto fail;

  /* Convert to UTF-8 */
  ib = (char *)from;
  ibl = fromlen;
  ob = utfbuf;
  obl = utflen;
  for (;;) {
    k = iconv(cd1, &ib, &ibl, &ob, &obl);
    assert((!k && !ibl) ||
	   (k == (size_t)(-1) && errno == E2BIG && ibl && obl < 6) ||
	   (k == (size_t)(-1) &&
	    (errno == EILSEQ || errno == EINVAL) && ibl));
    if (!ibl)
      break;
    if (obl < 6) {
      /* Enlarge the buffer */
      if(utflen*2 < utflen) /* overflow check */
	goto fail;
      utflen *= 2;
      newbuf = realloc(utfbuf, utflen);
      if (!newbuf)
	goto fail;
      ob = (ob - utfbuf) + newbuf;
      obl = utflen - (ob - newbuf);
      utfbuf = newbuf;
    }
    else {
      /* Invalid input */
      ib++, ibl--;
      *ob++ = '#', obl--;
      ret = 2;
      iconv(cd1, 0, 0, 0, 0);
    }
  }

  if (cd2 == (iconv_t)(-1)) {
    /* The target encoding was UTF-8 */
    if (tolen)
      *tolen = ob - utfbuf;
    if (!to) {
      free(utfbuf);
      iconv_close(cd1);
      return ret;
    }
    newbuf = safe_realloc_add_2op_(utfbuf, (ob - utfbuf), /*+*/1);
    if (!newbuf)
      goto fail;
    ob = (ob - utfbuf) + newbuf;
    *ob = '\0';
    *to = newbuf;
    iconv_close(cd1);
    return ret;
  }

  /* Truncate the buffer to be tidy */
  utflen = ob - utfbuf;
  newbuf = realloc(utfbuf, utflen);
  if (!newbuf)
    goto fail;
  utfbuf = newbuf;

  /* Convert from UTF-8 to discover how long the output is */
  outlen = 0;
  ib = utfbuf;
  ibl = utflen;
  while (ibl) {
    ob = tbuf;
    obl = sizeof(tbuf);
    k = iconv(cd2, &ib, &ibl, &ob, &obl);
    assert((k != (size_t)(-1) && !ibl) ||
	   (k == (size_t)(-1) && errno == E2BIG && ibl) ||
	   (k == (size_t)(-1) && errno == EILSEQ && ibl));
    if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
      /* Replace one character */
      char *tb = "?";
      size_t tbl = 1;

      outlen += ob - tbuf;
      ob = tbuf;
      obl = sizeof(tbuf);
      k = iconv(cd2, &tb, &tbl, &ob, &obl);
      assert((!k && !tbl) ||
	     (k == (size_t)(-1) && errno == EILSEQ && tbl));
      for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
	;
    }
    outlen += ob - tbuf;
  }
  ob = tbuf;
  obl = sizeof(tbuf);
  k = iconv(cd2, 0, 0, &ob, &obl);
  assert(!k);
  outlen += ob - tbuf;

  /* Convert from UTF-8 for real */
  outbuf = safe_malloc_add_2op_(outlen, /*+*/1);
  if (!outbuf)
    goto fail;
  ib = utfbuf;
  ibl = utflen;
  ob = outbuf;
  obl = outlen;
  while (ibl) {
    k = iconv(cd2, &ib, &ibl, &ob, &obl);
    assert((k != (size_t)(-1) && !ibl) ||
	   (k == (size_t)(-1) && errno == EILSEQ && ibl));
    if (k && !ret)
      ret = 1;
    if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
      /* Replace one character */
      char *tb = "?";
      size_t tbl = 1;

      k = iconv(cd2, &tb, &tbl, &ob, &obl);
      assert((!k && !tbl) ||
	     (k == (size_t)(-1) && errno == EILSEQ && tbl));
      for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
	;
    }
  }
  k = iconv(cd2, 0, 0, &ob, &obl);
  assert(!k);
  assert(!obl);
  *ob = '\0';

  free(utfbuf);
  iconv_close(cd1);
  iconv_close(cd2);
  if (tolen)
    *tolen = outlen;
  if (!to) {
    free(outbuf);
    return ret;
  }
  *to = outbuf;
  return ret;

 fail:
  if(0 != utfbuf)
    free(utfbuf);
  iconv_close(cd1);
  if (cd2 != (iconv_t)(-1))
    iconv_close(cd2);
  return -2;
}