static svn_error_t * test_stream_base64(apr_pool_t *pool) { svn_stream_t *stream; svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool); svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool); int i; static const char *strings[] = { "fairly boring test data... blah blah", "A", "abc", "012345679", NULL }; stream = svn_stream_from_stringbuf(actual, pool); stream = svn_base64_decode(stream, pool); stream = svn_base64_encode(stream, pool); for (i = 0; strings[i]; i++) { apr_size_t len = strlen(strings[i]); svn_stringbuf_appendbytes(expected, strings[i], len); SVN_ERR(svn_stream_write(stream, strings[i], &len)); } SVN_ERR(svn_stream_close(stream)); SVN_TEST_STRING_ASSERT(actual->data, expected->data); return SVN_NO_ERROR; }
/* Conforms to svn_ra_serf__xml_opened_t */ static svn_error_t * blame_opened(svn_ra_serf__xml_estate_t *xes, void *baton, int entered_state, const svn_ra_serf__dav_props_t *tag, apr_pool_t *scratch_pool) { blame_context_t *blame_ctx = baton; if (entered_state == FILE_REV) { apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes); /* Child elements will store properties in these structures. */ blame_ctx->rev_props = apr_hash_make(state_pool); blame_ctx->prop_diffs = apr_array_make(state_pool, 5, sizeof(svn_prop_t)); blame_ctx->state_pool = state_pool; /* Clear this, so we can detect the absence of a TXDELTA. */ blame_ctx->stream = NULL; } else if (entered_state == TXDELTA) { apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes); apr_hash_t *gathered = svn_ra_serf__xml_gather_since(xes, FILE_REV); const char *path; const char *rev_str; const char *merged_revision; svn_txdelta_window_handler_t txdelta; void *txdelta_baton; apr_int64_t rev; path = svn_hash_gets(gathered, "path"); rev_str = svn_hash_gets(gathered, "rev"); SVN_ERR(svn_cstring_atoi64(&rev, rev_str)); merged_revision = svn_hash_gets(gathered, "merged-revision"); SVN_ERR(blame_ctx->file_rev(blame_ctx->file_rev_baton, path, (svn_revnum_t)rev, blame_ctx->rev_props, merged_revision != NULL, &txdelta, &txdelta_baton, blame_ctx->prop_diffs, state_pool)); blame_ctx->stream = svn_base64_decode(svn_txdelta_parse_svndiff( txdelta, txdelta_baton, TRUE /* error_on_early_close */, state_pool), state_pool); } return SVN_NO_ERROR; }
/* This test doesn't test much unless run under valgrind when it triggers the problem reported here: http://mail-archives.apache.org/mod_mbox/subversion-dev/201202.mbox/%[email protected]%3E The two data writes caused the base 64 code to allocate a buffer that was a byte short but exactly matched a stringbuf blocksize. That meant the stringbuf didn't overallocate and a write beyond the end of the buffer occurred. */ static svn_error_t * test_stream_base64_2(apr_pool_t *pool) { const struct data_t { const char *encoded1; const char *encoded2; } data[] = { { "MTI", "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "A23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "B23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "C23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "D23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "E23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "F23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "G23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "H23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "I23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D123456789E" "623456789A123456789B123456789C123456789D123456789E" "723456789A123456789B123456789C123456789D123456789E" "823456789A123456789B123456789C123456789D123456789E" "923456789A123456789B123456789C123456789D123456789E" "J23456789A123456789B123456789C123456789D123456789E" "123456789A123456789B123456789C123456789D123456789E" "223456789A123456789B123456789C123456789D123456789E" "323456789A123456789B123456789C123456789D123456789E" "423456789A123456789B123456789C123456789D123456789E" "523456789A123456789B123456789C123456789D12345" }, { NULL, NULL, }, }; int i; for (i = 0; data[i].encoded1; i++) { apr_size_t len1 = strlen(data[i].encoded1); svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool); svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool); svn_stream_t *stream = svn_stream_from_stringbuf(actual, pool); stream = svn_base64_encode(stream, pool); stream = svn_base64_decode(stream, pool); SVN_ERR(svn_stream_write(stream, data[i].encoded1, &len1)); svn_stringbuf_appendbytes(expected, data[i].encoded1, len1); if (data[i].encoded2) { apr_size_t len2 = strlen(data[i].encoded2); SVN_ERR(svn_stream_write(stream, data[i].encoded2, &len2)); svn_stringbuf_appendbytes(expected, data[i].encoded2, len2); } SVN_ERR(svn_stream_close(stream)); } return SVN_NO_ERROR; }
static svn_error_t * start_element(int *elem, void *baton, int parent_state, const char *nspace, const char *elt_name, const char **atts) { replay_baton_t *rb = baton; const svn_ra_neon__xml_elm_t *elm = svn_ra_neon__lookup_xml_elem(editor_report_elements, nspace, elt_name); if (! elm) { *elem = NE_XML_DECLINE; return SVN_NO_ERROR; } if (parent_state == ELEM_root) { /* If we're at the root of the tree, the element has to be the editor * report itself. */ if (elm->id != ELEM_editor_report) return UNEXPECTED_ELEMENT(nspace, elt_name); } else if (parent_state != ELEM_editor_report) { /* If we're not at the root, our parent has to be the editor report, * since we don't actually nest any elements. */ return UNEXPECTED_ELEMENT(nspace, elt_name); } switch (elm->id) { case ELEM_target_revision: { const char *crev = svn_xml_get_attr_value("rev", atts); if (! crev) return MISSING_ATTR(nspace, elt_name, "rev"); else return rb->editor->set_target_revision(rb->edit_baton, SVN_STR_TO_REV(crev), rb->pool); } break; case ELEM_open_root: { const char *crev = svn_xml_get_attr_value("rev", atts); if (! crev) return MISSING_ATTR(nspace, elt_name, "rev"); else { apr_pool_t *subpool = svn_pool_create(rb->pool); void *dir_baton; SVN_ERR(rb->editor->open_root(rb->edit_baton, SVN_STR_TO_REV(crev), subpool, &dir_baton)); push_dir(rb, dir_baton, "", subpool); } } break; case ELEM_delete_entry: { const char *path = svn_xml_get_attr_value("name", atts); const char *crev = svn_xml_get_attr_value("rev", atts); if (! path) return MISSING_ATTR(nspace, elt_name, "name"); else if (! crev) return MISSING_ATTR(nspace, elt_name, "rev"); else { dir_item_t *di = &TOP_DIR(rb); SVN_ERR(rb->editor->delete_entry(path, SVN_STR_TO_REV(crev), di->baton, di->pool)); } } break; case ELEM_open_directory: case ELEM_add_directory: { const char *crev = svn_xml_get_attr_value("rev", atts); const char *name = svn_xml_get_attr_value("name", atts); if (! name) return MISSING_ATTR(nspace, elt_name, "name"); else { dir_item_t *parent = &TOP_DIR(rb); apr_pool_t *subpool = svn_pool_create(parent->pool); svn_revnum_t rev; void *dir_baton; if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; if (elm->id == ELEM_open_directory) SVN_ERR(rb->editor->open_directory(name, parent->baton, rev, subpool, &dir_baton)); else if (elm->id == ELEM_add_directory) { const char *cpath = svn_xml_get_attr_value("copyfrom-path", atts); crev = svn_xml_get_attr_value("copyfrom-rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; SVN_ERR(rb->editor->add_directory(name, parent->baton, cpath, rev, subpool, &dir_baton)); } else SVN_ERR_MALFUNCTION(); push_dir(rb, dir_baton, name, subpool); } } break; case ELEM_open_file: case ELEM_add_file: { const char *path = svn_xml_get_attr_value("name", atts); svn_revnum_t rev; dir_item_t *parent = &TOP_DIR(rb); if (! path) return MISSING_ATTR(nspace, elt_name, "name"); svn_pool_clear(parent->file_pool); if (elm->id == ELEM_add_file) { const char *cpath = svn_xml_get_attr_value("copyfrom-path", atts); const char *crev = svn_xml_get_attr_value("copyfrom-rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; SVN_ERR(rb->editor->add_file(path, parent->baton, cpath, rev, parent->file_pool, &rb->file_baton)); } else { const char *crev = svn_xml_get_attr_value("rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; SVN_ERR(rb->editor->open_file(path, parent->baton, rev, parent->file_pool, &rb->file_baton)); } } break; case ELEM_apply_textdelta: if (! rb->file_baton) return svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got apply-textdelta element without preceding " "add-file or open-file")); else { const char *checksum = svn_xml_get_attr_value("checksum", atts); SVN_ERR(rb->editor->apply_textdelta(rb->file_baton, checksum, TOP_DIR(rb).file_pool, &rb->whandler, &rb->whandler_baton)); rb->svndiff_decoder = svn_txdelta_parse_svndiff (rb->whandler, rb->whandler_baton, TRUE, TOP_DIR(rb).file_pool); rb->base64_decoder = svn_base64_decode(rb->svndiff_decoder, TOP_DIR(rb).file_pool); } break; case ELEM_close_file: if (! rb->file_baton) return svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got close-file element without preceding " "add-file or open-file")); else { const char *checksum = svn_xml_get_attr_value("checksum", atts); SVN_ERR(rb->editor->close_file(rb->file_baton, checksum, TOP_DIR(rb).file_pool)); rb->file_baton = NULL; } break; case ELEM_close_directory: if (rb->dirs->nelts == 0) return svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got close-directory element without ever opening " "a directory")); else { dir_item_t *di = &TOP_DIR(rb); SVN_ERR(rb->editor->close_directory(di->baton, di->pool)); svn_pool_destroy(di->pool); apr_array_pop(rb->dirs); } break; case ELEM_change_file_prop: case ELEM_change_dir_prop: { const char *name = svn_xml_get_attr_value("name", atts); if (! name) return MISSING_ATTR(nspace, elt_name, "name"); else { svn_pool_clear(rb->prop_pool); if (svn_xml_get_attr_value("del", atts)) rb->prop_accum = NULL; else rb->prop_accum = svn_stringbuf_create("", rb->prop_pool); rb->prop_name = apr_pstrdup(rb->prop_pool, name); } } break; } *elem = elm->id; return SVN_NO_ERROR; }