TEST(chunk, decode_message) { struct mbuf *mb_chunked = mbuf_alloc(1024); struct mbuf *mb_data = mbuf_alloc(1024); int err = 0; ASSERT_TRUE(mb_chunked != NULL); ASSERT_TRUE(mb_data != NULL); mbuf_write_str(mb_chunked, encoded_data); mb_chunked->pos = 0; /* decode all chunks */ for (int i=0; i<16; i++) { uint8_t *p; size_t n; err = chunk_decode(&p, &n, mb_chunked); if (err) break; if (n == 0) break; err = mbuf_write_mem(mb_data, p, n); if (err) break; } ASSERT_EQ(str_len(decoded_data), mb_data->end); ASSERT_TRUE(0 == memcmp(decoded_data, mb_data->buf, mb_data->end)); mem_deref(mb_chunked); mem_deref(mb_data); }
TEST(chunk, decode_invalid_header) { struct mbuf *mb = mbuf_alloc(1024); int err = 0; mbuf_write_str(mb, "alfred\r\n"); mb->pos = 0; err = chunk_decode(NULL, NULL, mb); ASSERT_EQ(EBADMSG, err); mem_deref(mb); }
TEST(chunk, decode_incomplete_header) { struct mbuf *mb = mbuf_alloc(1024); int err = 0; mbuf_write_str(mb, "c8"); /* the CRLF is missing here */ mb->pos = 0; err = chunk_decode(NULL, NULL, mb); ASSERT_EQ(EBADMSG, err); mem_deref(mb); }
TEST(chunk, decode_too_short) { struct mbuf *mb_chunked = mbuf_alloc(1024); int err = 0; mbuf_write_str(mb_chunked, "3\r\nab"); mb_chunked->pos = 0; err = chunk_decode(NULL, NULL, mb_chunked); ASSERT_EQ(EBADMSG, err); mem_deref(mb_chunked); }
/** * \brief Decode Base64 encoded string to binary data * * Decode Base64 encoded string \p in to binary data \p out * * \param in Reference to a Base64 encoded string * \param in_sz length of \p in in bytes (excluding the terminating \c NUL) * \param out Pre-allocated buffer of size approx as \p in_sz * \param out_sz Value-result argument initially containing the total * size of \p out in bytes. On successful return it * holds the decoded buffer size. * * \retval 0 on success * \retval ~0 on failure */ int u_b64_decode (const char *in, size_t in_sz, uint8_t *out, size_t *out_sz) { char buf[4]; size_t i, len, pad, tot_sz = *out_sz; uint8_t *pout; dbg_return_if (in == NULL, ~0); dbg_return_if (in_sz == 0, ~0); dbg_return_if (out == NULL, ~0); dbg_return_if (out_sz == NULL, ~0); for (pout = out; in_sz; ) { for (pad = 0, len = 0, i = 0; i < 4; ++i) { if (in_sz && in_sz-- > 0) /* Avoid wrapping around in_sz. */ { buf[i] = *in++; if (buf[i] == '=') ++pad; else if (!is_base64(buf[i])) return ~0; ++len; } else buf[i] = '\0'; } if (len) { size_t nlen = 3 - pad; if (tot_sz >= nlen) { chunk_decode(buf, pout); tot_sz -= nlen; /* Take care of subtracting pad bytes. */ pout += nlen; } else return ~0; /* Not enough space. */ } } *out_sz -= tot_sz; return 0; }
int wav_header_decode(struct wav_fmt *fmt, size_t *datasize, FILE *f) { struct wav_chunk header, format, chunk; uint8_t rifftype[4]; /* "WAVE" */ int err = 0; err = chunk_decode(&header, f); if (err) return err; if (memcmp(header.id, "RIFF", 4)) { (void)re_fprintf(stderr, "aufile: expected RIFF (%b)\n", header.id, 4); return EBADMSG; } if (1 != fread(rifftype, sizeof(rifftype), 1, f)) return ferror(f); if (memcmp(rifftype, "WAVE", 4)) { (void)re_fprintf(stderr, "aufile: expected WAVE (%b)\n", rifftype, 4); return EBADMSG; } err = chunk_decode(&format, f); if (err) return err; if (memcmp(format.id, "fmt ", 4)) { (void)re_fprintf(stderr, "aufile: expected fmt (%b)\n", format.id, 4); return EBADMSG; } if (format.size < WAVE_FMT_SIZE) return EBADMSG; err = read_u16(f, &fmt->format); err |= read_u16(f, &fmt->channels); err |= read_u32(f, &fmt->srate); err |= read_u32(f, &fmt->byterate); err |= read_u16(f, &fmt->block_align); err |= read_u16(f, &fmt->bps); if (err) return err; /* skip any extra bytes */ if (format.size >= (WAVE_FMT_SIZE + 2)) { err = read_u16(f, &fmt->extra); if (err) return err; if (fmt->extra > 0) { if (fseek(f, fmt->extra, SEEK_CUR)) return errno; } } /* fast forward to "data" chunk */ for (;;) { err = chunk_decode(&chunk, f); if (err) return err; if (chunk.size > header.size) { (void)re_fprintf(stderr, "chunk size too large" " (%u > %u)\n", chunk.size, header.size); return EBADMSG; } if (0 == memcmp(chunk.id, "data", 4)) { *datasize = chunk.size; break; } if (fseek(f, chunk.size, SEEK_CUR) < 0) return errno; } return 0; }