From patchwork Wed Aug 10 18:37:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lucas De Marchi X-Patchwork-Id: 9273509 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B342860231 for ; Wed, 10 Aug 2016 18:37:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A3EBD2840F for ; Wed, 10 Aug 2016 18:37:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 988992841A; Wed, 10 Aug 2016 18:37:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0D7C028417 for ; Wed, 10 Aug 2016 18:37:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934101AbcHJShj (ORCPT ); Wed, 10 Aug 2016 14:37:39 -0400 Received: from mail-pa0-f67.google.com ([209.85.220.67]:33808 "EHLO mail-pa0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933215AbcHJShi (ORCPT ); Wed, 10 Aug 2016 14:37:38 -0400 Received: by mail-pa0-f67.google.com with SMTP id hh10so3232781pac.1 for ; Wed, 10 Aug 2016 11:37:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WomiO10ZF3+CRkDWLTgTVpOwC2uVlWYzXCZsYiRVUGo=; b=G8DRYhRRu9vnEZvfbGIJnBwzo+5iZQcv6cBL6GCbnaHfxhgh7EVJG35yuGWA0L3TFk dXAguecC7nShv9SxKpNNM26UV8f356f5s/mzWM7yXbN7pGyElQxFfmMV+1i1wczQVNU4 PHI7Y2A4c4v4YijjdVC0NxZ8ur1eY5NTffdtmDM91wrky1VvzTC/y41BwPCnjk3XTWte dxRFPOUJ8vSN+sqEc6noz4Rngrh/9rGiTqFf2zQKV7qcVOUFuzRF6+vIoUO0yTlcF3ir KqpVkcRgU8Mc+lBjuUYW3QRHiTZbt+23ECV17WxAGuNtkfKXJwVKGTm5hvNo3zg8G3X2 TlNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WomiO10ZF3+CRkDWLTgTVpOwC2uVlWYzXCZsYiRVUGo=; b=aG5RD52FU/lpZNCcm4PfgLVpZUM621ZiFBdlipGMlhWHP+igcwh4kvPi6mqU4bSpdX AJIx02OoCqMBBPW/c3zWuizFcnZZojYfDKAM7wbGrXGVb3Xh5y6nj1sALlx7dQDrM5FW RN9IGMDedlf7i/kLMGSWrxY7zIlUz7O99Lgsucc4feG70sDh3E57Ij3IQJ/mRw5KyQqN qS2pyn/isXM6iTz2CTLo+7vUvETT1M3KTcGDJgF0IRODhbqEbmbrMaKFfMmhl3kiY1fm RXAa+pLZbG/JGSkJBdyFYKwCxUimXVLpODUyqO+aB93yALiebZRvTDp2DhJBuBMIj2CB NQmw== X-Gm-Message-State: AEkooutpdNPbBDd/v18cl2gc97AEshqxx/Dk25I3aaCn3/zQLLb+5wIELq8arOoEmdnlzA== X-Received: by 10.66.80.2 with SMTP id n2mr9580838pax.134.1470854257315; Wed, 10 Aug 2016 11:37:37 -0700 (PDT) Received: from ldmartin-desk.amr.corp.intel.com (jfdmzpr02-ext.jf.intel.com. [134.134.137.71]) by smtp.gmail.com with ESMTPSA id s1sm65863315paz.47.2016.08.10.11.37.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Aug 2016 11:37:36 -0700 (PDT) From: Lucas De Marchi To: linux-modules@vger.kernel.org Cc: Lucas De Marchi Subject: [PATCH 2/3] Add scratchbuf implementation Date: Wed, 10 Aug 2016 15:37:12 -0300 Message-Id: <1470854233-19810-2-git-send-email-lucas.de.marchi@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1470854233-19810-1-git-send-email-lucas.de.marchi@gmail.com> References: <1470854233-19810-1-git-send-email-lucas.de.marchi@gmail.com> Sender: owner-linux-modules@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Lucas De Marchi This should fill the requirements for "we need to loop over a lot of strings that usually are small enough to remain on stack, but we want to protect ourselves against huge strings not fitting in the static buffer we estimated as sufficient" --- Makefile.am | 5 +++ shared/scratchbuf.c | 60 ++++++++++++++++++++++++++++++ shared/scratchbuf.h | 23 ++++++++++++ testsuite/.gitignore | 3 ++ testsuite/test-scratchbuf.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+) create mode 100644 shared/scratchbuf.c create mode 100644 shared/scratchbuf.h create mode 100644 testsuite/test-scratchbuf.c diff --git a/Makefile.am b/Makefile.am index 390628a..d4eeb7e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ shared_libshared_la_SOURCES = \ shared/array.h \ shared/hash.c \ shared/hash.h \ + shared/scratchbuf.c \ shared/strbuf.c \ shared/strbuf.h \ shared/util.c \ @@ -322,6 +323,7 @@ testsuite_libtestsuite_la_LIBADD = -lrt TESTSUITE = \ testsuite/test-hash \ testsuite/test-array \ + testsuite/test-scratchbuf \ testsuite/test-strbuf \ testsuite/test-init \ testsuite/test-initstate \ @@ -349,6 +351,9 @@ testsuite_test_hash_CPPFLAGS = $(TESTSUITE_CPPFLAGS) testsuite_test_array_LDADD = $(TESTSUITE_LDADD) testsuite_test_array_CPPFLAGS = $(TESTSUITE_CPPFLAGS) +testsuite_test_scratchbuf_LDADD = $(TESTSUITE_LDADD) +testsuite_test_scratchbuf_CPPFLAGS = $(TESTSUITE_CPPFLAGS) + testsuite_test_strbuf_LDADD = $(TESTSUITE_LDADD) testsuite_test_strbuf_CPPFLAGS = $(TESTSUITE_CPPFLAGS) diff --git a/shared/scratchbuf.c b/shared/scratchbuf.c new file mode 100644 index 0000000..8d9eb83 --- /dev/null +++ b/shared/scratchbuf.c @@ -0,0 +1,60 @@ +/* + * kmod - interface to kernel module operations + * + * Copyright (C) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "scratchbuf.h" + +#include +#include + +void scratchbuf_init(struct scratchbuf *buf, char *stackbuf, size_t size) +{ + buf->bytes = stackbuf; + buf->size = size; + buf->need_free = false; +} + +int scratchbuf_alloc(struct scratchbuf *buf, size_t size) +{ + char *tmp; + + if (size <= buf->size) + return 0; + + if (buf->need_free) { + tmp = realloc(buf->bytes, size); + if (tmp == NULL) + return -ENOMEM; + } else { + tmp = malloc(size); + if (tmp == NULL) + return -ENOMEM; + memcpy(tmp, buf->bytes, buf->size); + } + + buf->size = size; + buf->bytes = tmp; + buf->need_free = true; + + return 0; +} + +void scratchbuf_release(struct scratchbuf *buf) +{ + if (buf->need_free) + free(buf->bytes); +} diff --git a/shared/scratchbuf.h b/shared/scratchbuf.h new file mode 100644 index 0000000..d14fd14 --- /dev/null +++ b/shared/scratchbuf.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +/* + * Buffer abstract data type + */ +struct scratchbuf { + char *bytes; + size_t size; + bool need_free; +}; + +void scratchbuf_init(struct scratchbuf *buf, char *stackbuf, size_t size); +int scratchbuf_alloc(struct scratchbuf *buf, size_t sz); +void scratchbuf_release(struct scratchbuf *buf); + +/* Return a C string */ +inline char *scratchbuf_str(struct scratchbuf *buf) +{ + return buf->bytes; +} diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 2b71a47..9d26b88 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -2,6 +2,7 @@ *.la *.so /.dirstamp +/test-scratchbuf /test-strbuf /test-array /test-util @@ -20,6 +21,8 @@ /test-tools /rootfs /stamp-rootfs +/test-scratchbuf.log +/test-scratchbuf.trs /test-strbuf.log /test-strbuf.trs /test-array.log diff --git a/testsuite/test-scratchbuf.c b/testsuite/test-scratchbuf.c new file mode 100644 index 0000000..6d86957 --- /dev/null +++ b/testsuite/test-scratchbuf.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include + +#include + +#include "testsuite.h" + +static int test_scratchbuf_onlystack(const struct test *t) +{ + struct scratchbuf sbuf; + const char *smallstr = "xyz"; + char buf[3 + 2]; + char buf2[3 + 1]; + + scratchbuf_init(&sbuf, buf, sizeof(buf)); + assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE); + assert_return(sbuf.need_free == false, EXIT_FAILURE); + scratchbuf_release(&sbuf); + + scratchbuf_init(&sbuf, buf2, sizeof(buf2)); + assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE); + assert_return(sbuf.need_free == false, EXIT_FAILURE); + scratchbuf_release(&sbuf); + + memcpy(scratchbuf_str(&sbuf), smallstr, strlen(smallstr) + 1); + assert_return(strcmp(scratchbuf_str(&sbuf), smallstr) == 0, EXIT_FAILURE); + + return 0; +} +DEFINE_TEST(test_scratchbuf_onlystack, + .description = "test scratchbuf for buffer on stack only"); + + +static int test_scratchbuf_heap(const struct test *t) +{ + struct scratchbuf sbuf; + const char *smallstr = "xyz"; + const char *largestr = "xyzxyzxyz"; + const char *largestr2 = "xyzxyzxyzxyzxyz"; + char buf[3 + 1]; + + scratchbuf_init(&sbuf, buf, sizeof(buf)); + + /* Initially only on stack */ + assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE); + assert_return(sbuf.need_free == false, EXIT_FAILURE); + memcpy(scratchbuf_str(&sbuf), smallstr, strlen(smallstr) + 1); + + /* Grow once to heap */ + assert_return(scratchbuf_alloc(&sbuf, strlen(largestr) + 1) == 0, EXIT_FAILURE); + assert_return(sbuf.need_free == true, EXIT_FAILURE); + assert_return(sbuf.size == strlen(largestr) + 1, EXIT_FAILURE); + assert_return(strcmp(scratchbuf_str(&sbuf), smallstr) == 0, EXIT_FAILURE); + memcpy(scratchbuf_str(&sbuf), largestr, strlen(largestr) + 1); + assert_return(strcmp(scratchbuf_str(&sbuf), largestr) == 0, EXIT_FAILURE); + + /* Grow again - realloc should take place */ + assert_return(scratchbuf_alloc(&sbuf, strlen(largestr2) + 1) == 0, EXIT_FAILURE); + assert_return(sbuf.need_free == true, EXIT_FAILURE); + assert_return(sbuf.size == strlen(largestr2) + 1, EXIT_FAILURE); + memcpy(scratchbuf_str(&sbuf), largestr2, strlen(largestr2) + 1); + assert_return(strcmp(scratchbuf_str(&sbuf), largestr2) == 0, EXIT_FAILURE); + + scratchbuf_release(&sbuf); + + return 0; +} +DEFINE_TEST(test_scratchbuf_heap, + .description = "test scratchbuf for buffer on that grows to heap"); + +TESTSUITE_MAIN();