Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 48 additions & 12 deletions external/sundown/Project/sundown/markdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@

#include "markdown.h"
#include "stack.h"
#include "siphash.h"

#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 25
#include <sys/random.h>
#else
# define getrandom backport_getrandom
# include <sys/syscall.h>
#endif

#if defined(_WIN32)
#define strncasecmp _strnicmp
#endif
Expand All @@ -50,6 +58,7 @@ struct link_ref {
unsigned int id;

struct buf *link;
struct buf *label;
struct buf *title;

struct link_ref *next;
Expand Down Expand Up @@ -118,10 +127,18 @@ struct sd_markdown {
int in_link_body;
};

int sip_hash_key_init = 0;
uint8_t sip_hash_key[SIP_HASH_KEY_LEN];

/***************************
* HELPER FUNCTIONS *
***************************/

int backport_getrandom(void *buf, size_t buflen, unsigned int flags)
{
return (int)syscall(SYS_getrandom, buf, buflen, flags);
}

static inline struct buf *
rndr_newbuf(struct sd_markdown *rndr, int type)
{
Expand Down Expand Up @@ -170,26 +187,35 @@ unscape_text(struct buf *ob, struct buf *src)
static unsigned int
hash_link_ref(const uint8_t *link_ref, size_t length)
{
size_t i;
unsigned int hash = 0;

for (i = 0; i < length; ++i)
hash = tolower(link_ref[i]) + (hash << 6) + (hash << 16) - hash;

return hash;
return siphash_nocase(link_ref, length, sip_hash_key);
}

static struct link_ref *
add_link_ref(
struct link_ref **references,
const uint8_t *name, size_t name_size)
{
struct link_ref *ref = calloc(1, sizeof(struct link_ref));
unsigned int hash;
struct link_ref *ref;
hash = hash_link_ref(name, name_size);
ref = references[hash % REF_TABLE_SIZE];
while (ref != NULL) {
/* If a reference with the same label exists already, replace it with the new reference */
if (ref->id == hash && ref->label->size == name_size) {
if (strncasecmp((char *)ref->label->data, (char *) name, name_size) == 0) {
bufrelease(ref->label);
bufrelease(ref->link);
bufrelease(ref->title);
return ref;
}
}

ref = ref->next;
}
ref = calloc(1, sizeof(struct link_ref));
if (!ref)
return NULL;

ref->id = hash_link_ref(name, name_size);
ref->id = hash;
ref->next = references[ref->id % REF_TABLE_SIZE];

references[ref->id % REF_TABLE_SIZE] = ref;
Expand All @@ -205,8 +231,11 @@ find_link_ref(struct link_ref **references, uint8_t *name, size_t length)
ref = references[hash % REF_TABLE_SIZE];

while (ref != NULL) {
if (ref->id == hash)
return ref;
if (ref->id == hash && ref->label->size == length) {
if (strncasecmp((char *)ref->label->data, (char *) name, length) == 0) {
return ref;
}
}

ref = ref->next;
}
Expand All @@ -225,6 +254,7 @@ free_link_refs(struct link_ref **references)

while (r) {
next = r->next;
bufrelease(r->label);
bufrelease(r->link);
bufrelease(r->title);
free(r);
Expand Down Expand Up @@ -2408,6 +2438,12 @@ sd_markdown_new(
if (!md)
return NULL;

if (!sip_hash_key_init) {
if (getrandom(sip_hash_key, SIP_HASH_KEY_LEN, 0) < SIP_HASH_KEY_LEN)
return NULL;
sip_hash_key_init = 1;
}

memcpy(&md->cb, callbacks, sizeof(struct sd_callbacks));

stack_init(&md->work_bufs[BUFFER_BLOCK], 4);
Expand Down
Loading