Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Moving entity-escaping in attributes from the parser to the renderer

The following arguments to callbacks are no longer escaped by the parser:
- link in autolink()
- link and title in link()
- link, title and alt in image()

To help custom renderers, lus_attr_escape() is exported, which escapes
'<', '>', '&' and '"' from the input, replacing them by entities.
  • Loading branch information...
commit 6057cae51dc9bac3a42205c5a61811a1c6860ff4 1 parent b795385
Natacha Porté authored
Showing with 73 additions and 54 deletions.
  1. +13 −35 markdown.c
  2. +45 −19 renderers.c
  3. +15 −0 renderers.h
View
48 markdown.c
@@ -104,18 +104,6 @@ static struct html_tag block_tags[] = {
* STATIC HELPER FUNCTIONS *
***************************/
-/* attr_escape • copy data into a buffer, escaping '"', '<' '&' and '>' */
-static void
-attr_escape(struct buf *ob, char *data, size_t size) {
- size_t i;
- for (i = 0; i < size; i += 1)
- if (data[i] == '&') BUFPUTSL(ob, "&amp;");
- else if (data[i] == '<') BUFPUTSL(ob, "&lt;");
- else if (data[i] == '>') BUFPUTSL(ob, "&gt;");
- else if (data[i] == '"') BUFPUTSL(ob, "&quot;");
- else bufputc(ob, data[i]); }
-
-
/* html_escape • copy data into a buffer, escaping '<' '&' and '>' */
static void
html_escape(struct buf *ob, char *data, size_t size) {
@@ -551,17 +539,10 @@ char_langle_tag(struct buf *ob, struct render *rndr,
int ret = 0;
if (end) {
if (rndr->make.autolink && altype != MKDA_NOT_AUTOLINK) {
- struct buf *wk = 0;
- if (rndr->work.size < rndr->work.asize) {
- wk = rndr->work.item[rndr->work.size ++];
- wk->size = 0; }
- else {
- wk = bufnew(WORK_UNIT);
- parr_push(&rndr->work, wk); }
- attr_escape(wk, data + 1, end - 2);
- ret = rndr->make.autolink(ob, wk, altype,
- rndr->make.opaque);
- rndr->work.size -= 1; }
+ work.data = data + 1;
+ work.size = end - 2;
+ ret = rndr->make.autolink(ob, &work, altype,
+ rndr->make.opaque); }
else if (rndr->make.raw_html_tag)
ret = rndr->make.raw_html_tag(ob, &work,
rndr->make.opaque); }
@@ -663,7 +644,7 @@ char_link(struct buf *ob, struct render *rndr,
else {
link = bufnew(WORK_UNIT);
parr_push(&rndr->work, link); }
- attr_escape(link, data + link_b, link_e - link_b); }
+ bufput(link, data + link_b, link_e - link_b); }
if (title_e > title_b) {
if (rndr->work.size < rndr->work.asize) {
title = rndr->work.item[rndr->work.size ++];
@@ -671,7 +652,7 @@ char_link(struct buf *ob, struct render *rndr,
else {
title = bufnew(WORK_UNIT);
parr_push(&rndr->work, title); }
- attr_escape(title, data + title_b, title_e - title_b);}
+ bufput(title, data + title_b, title_e - title_b);}
i += 1; }
@@ -764,7 +745,7 @@ char_link(struct buf *ob, struct render *rndr,
else {
content = bufnew(WORK_UNIT);
parr_push(&rndr->work, content); }
- if (is_img) attr_escape(content, data + 1, txt_e - 1);
+ if (is_img) bufput(content, data + 1, txt_e - 1);
else parse_inline(content, rndr, data + 1, txt_e - 1); }
/* calling the relevant rendering function */
@@ -1455,18 +1436,15 @@ is_ref(char *data, size_t beg, size_t end, size_t *last, struct array *refs) {
id.size = id_end - id_offset;
n = arr_sorted_find_i(refs, &id, cmp_link_ref);
if (arr_insert(refs, 1, n) && (lr = arr_item(refs, n)) != 0) {
- struct buf *work = bufnew(WORK_UNIT);
lr->id = bufnew(id_end - id_offset);
bufput(lr->id, data + id_offset, id_end - id_offset);
- attr_escape(work, data + link_offset, link_end - link_offset);
- lr->link = bufdup(work, 1);
+ lr->link = bufnew(link_end - link_offset);
+ bufput(lr->link, data + link_offset, link_end - link_offset);
if (title_end > title_offset) {
- work->size = 0;
- attr_escape(work, data + title_offset,
- title_end - title_offset);
- lr->title = bufdup(work, 1); }
- else lr->title = 0;
- bufrelease(work); }
+ lr->title = bufnew(title_end - title_offset);
+ bufput(lr->title, data + title_offset,
+ title_end - title_offset); }
+ else lr->title = 0; }
return 1; }
View
64 renderers.c
@@ -21,6 +21,32 @@
#include <strings.h>
+/*****************************
+ * EXPORTED HELPER FUNCTIONS *
+ *****************************/
+
+/* lus_attr_escape • copy the buffer entity-escaping '<', '>', '&' and '"' */
+void
+lus_attr_escape(struct buf *ob, char *src, size_t size) {
+ size_t i = 0, org;
+ while (i < size) {
+ /* copying directly unescaped characters */
+ org = i;
+ while (i < size && src[i] != '<' && src[i] != '>'
+ && src[i] != '&' && src[i] != '"')
+ i += 1;
+ if (i > org) bufput(ob, src + org, i - org);
+
+ /* escaping */
+ if (i >= size) break;
+ else if (src[i] == '<') BUFPUTSL(ob, "&lt;");
+ else if (src[i] == '>') BUFPUTSL(ob, "&gt;");
+ else if (src[i] == '&') BUFPUTSL(ob, "&amp;");
+ else if (src[i] == '"') BUFPUTSL(ob, "&quot;");
+ i += 1; } }
+
+
+
/********************
* GENERIC RENDERER *
********************/
@@ -31,11 +57,11 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type,
if (!link || !link->size) return 0;
BUFPUTSL(ob, "<a href=\"");
if (type == MKDA_IMPLICIT_EMAIL) BUFPUTSL(ob, "mailto:");
- bufput(ob, link->data, link->size);
+ lus_attr_escape(ob, link->data, link->size);
BUFPUTSL(ob, "\">");
if (type == MKDA_EXPLICIT_EMAIL && link->size > 7)
- bufput(ob, link->data + 7, link->size - 7);
- else bufput(ob, link->data, link->size);
+ lus_attr_escape(ob, link->data + 7, link->size - 7);
+ else lus_attr_escape(ob, link->data, link->size);
BUFPUTSL(ob, "</a>");
return 1; }
@@ -87,10 +113,10 @@ static int
rndr_link(struct buf *ob, struct buf *link, struct buf *title,
struct buf *content, void *opaque) {
BUFPUTSL(ob, "<a href=\"");
- if (link && link->size) bufput(ob, link->data, link->size);
+ if (link && link->size) lus_attr_escape(ob, link->data, link->size);
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- bufput(ob, title->data, title->size); }
+ lus_attr_escape(ob, title->data, title->size); }
BUFPUTSL(ob, "\">");
if (content && content->size) bufput(ob, content->data, content->size);
BUFPUTSL(ob, "</a>");
@@ -161,13 +187,13 @@ html_image(struct buf *ob, struct buf *link, struct buf *title,
struct buf *alt, void *opaque) {
if (!link || !link->size) return 0;
BUFPUTSL(ob, "<img src=\"");
- bufput(ob, link->data, link->size);
+ lus_attr_escape(ob, link->data, link->size);
BUFPUTSL(ob, "\" alt=\"");
if (alt && alt->size)
- bufput(ob, alt->data, alt->size);
+ lus_attr_escape(ob, alt->data, alt->size);
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- bufput(ob, title->data, title->size); }
+ lus_attr_escape(ob, title->data, title->size); }
BUFPUTSL(ob, "\">");
return 1; }
@@ -217,13 +243,13 @@ xhtml_image(struct buf *ob, struct buf *link, struct buf *title,
struct buf *alt, void *opaque) {
if (!link || !link->size) return 0;
BUFPUTSL(ob, "<img src=\"");
- bufput(ob, link->data, link->size);
+ lus_attr_escape(ob, link->data, link->size);
BUFPUTSL(ob, "\" alt=\"");
if (alt && alt->size)
- bufput(ob, alt->data, alt->size);
+ lus_attr_escape(ob, alt->data, alt->size);
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- bufput(ob, title->data, title->size); }
+ lus_attr_escape(ob, title->data, title->size); }
BUFPUTSL(ob, "\" />");
return 1; }
@@ -281,7 +307,7 @@ print_link_wxh(struct buf *ob, struct buf *link) {
end += 1;
if (end == ex + 1) return 0;
/* everything is fine, proceeding to actual printing */
- bufput(ob, link->data, eq - 1);
+ lus_attr_escape(ob, link->data, eq - 1);
BUFPUTSL(ob, "\" width=");
bufput(ob, link->data + eq + 1, ex - eq - 1);
BUFPUTSL(ob, " height=");
@@ -294,14 +320,14 @@ discount_image(struct buf *ob, struct buf *link, struct buf *title,
if (!link || !link->size) return 0;
BUFPUTSL(ob, "<img src=\"");
if (!print_link_wxh(ob, link)) {
- bufput(ob, link->data, link->size);
+ lus_attr_escape(ob, link->data, link->size);
bufputc(ob, '"'); }
BUFPUTSL(ob, " alt=\"");
if (alt && alt->size)
- bufput(ob, alt->data, alt->size);
+ lus_attr_escape(ob, alt->data, alt->size);
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- bufput(ob, title->data, title->size); }
+ lus_attr_escape(ob, title->data, title->size); }
bufputs(ob, xhtml ? "\" />" : "\">");
return 1; }
@@ -321,27 +347,27 @@ discount_link(struct buf *ob, struct buf *link, struct buf *title,
if (!link) return rndr_link(ob, link, title, content, opaque);
else if (link->size > 5 && !strncasecmp(link->data, "abbr:", 5)) {
BUFPUTSL(ob, "<abbr title=\"");
- bufput(ob, link->data + 5, link->size - 5);
+ lus_attr_escape(ob, link->data + 5, link->size - 5);
BUFPUTSL(ob, "\">");
bufput(ob, content->data, content->size);
BUFPUTSL(ob, "</abbr>");
return 1; }
else if (link->size > 6 && !strncasecmp(link->data, "class:", 6)) {
BUFPUTSL(ob, "<span class=\"");
- bufput(ob, link->data + 6, link->size - 6);
+ lus_attr_escape(ob, link->data + 6, link->size - 6);
BUFPUTSL(ob, "\">");
bufput(ob, content->data, content->size);
BUFPUTSL(ob, "</span>");
return 1; }
else if (link->size > 3 && !strncasecmp(link->data, "id:", 3)) {
BUFPUTSL(ob, "<a id=\"");
- bufput(ob, link->data + 3, link->size - 3);
+ lus_attr_escape(ob, link->data + 3, link->size - 3);
BUFPUTSL(ob, "\">");
bufput(ob, content->data, content->size);
BUFPUTSL(ob, "</span>");
return 1; }
else if (link->size > 4 && !strncasecmp(link->data, "raw:", 4)) {
- bufput(ob, link->data + 4, link->size - 4);
+ lus_attr_escape(ob, link->data + 4, link->size - 4);
return 1; }
return rndr_link(ob, link, title, content, opaque); }
View
15 renderers.h
@@ -21,6 +21,21 @@
#include "markdown.h"
+
+/*****************************
+ * EXPORTED HELPER FUNCTIONS *
+ *****************************/
+
+/* lus_attr_escape • copy the buffer entity-escaping '<', '>', '&' and '"' */
+void
+lus_attr_escape(struct buf *ob, char *src, size_t size);
+
+
+
+/***********************
+ * RENDERER STRUCTURES *
+ ***********************/
+
/* original markdown renderers */
extern const struct mkd_renderer mkd_html; /* HTML 4 renderer */
extern const struct mkd_renderer mkd_xhtml; /* XHTML 1.0 renderer */
Please sign in to comment.
Something went wrong with that request. Please try again.