From nobody Sat Nov 23 16:43:35 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1723672915996685.8037897141171; Wed, 14 Aug 2024 15:01:55 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 99E6C13BB; Wed, 14 Aug 2024 18:01:38 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 9E13C1598; Wed, 14 Aug 2024 17:43:39 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 7718212DF; Wed, 14 Aug 2024 17:43:35 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 020BC14AE for ; Wed, 14 Aug 2024 17:43:20 -0400 (EDT) Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-588--pAackaKMKmDS6Yrhh-2qQ-1; Wed, 14 Aug 2024 17:43:19 -0400 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5E4B81944F06 for ; Wed, 14 Aug 2024 21:43:18 +0000 (UTC) Received: from hjs.brq.redhat.com (unknown [10.43.3.187]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id ADC611955E8C for ; Wed, 14 Aug 2024 21:43:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.6 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1723671800; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w4aNuasQkvRBSodHsYg0Dw1NJi5rxCfyTv9uqbi6Gig=; b=BXaA0nhXjAPjJnmB+gmyGDS3yc57C5ZqMBEHZpZzOVIzYy8PLv8O30ZMH2HZ2wnD7kUFiW Hjl+jZIwGMUFR9WSwKR3M0N6W1Rc8RbVOZb48wFHJFS80FVyHeUgoB3r2F35ozCPVHj3Xj Fg7ovRKTShuWfN0dTJ9nSdfAOVAy+I0= X-MC-Unique: -pAackaKMKmDS6Yrhh-2qQ-1 From: =?UTF-8?q?J=C3=A1n=20Tomko?= To: devel@lists.libvirt.org Subject: [libvirt PATCH 11/20] nss: convert findMACs to use json-c Date: Wed, 14 Aug 2024 23:40:26 +0200 Message-ID: <29547e96bd8f4b29aeee5286da8dc7c29add8f03.1723671635.git.jtomko@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: KTMEZTFWEKJRR2AU2CIISXPAXCJ7WX72 X-Message-ID-Hash: KTMEZTFWEKJRR2AU2CIISXPAXCJ7WX72 X-MailFrom: jtomko@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1723672916424116600 Content-Type: text/plain; charset="utf-8" While the parsing is still done by 1K buffers, the results are no longer filtered during the parsing, but the whole JSON has to live in memory at once, which was also the case before the NSS plugin dropped its dependency on libvirt_util. Also, the new parser might be more forgiving of missing elements. Signed-off-by: J=C3=A1n Tomko --- tools/nss/libvirt_nss_macs.c | 263 +++++++++-------------------------- 1 file changed, 68 insertions(+), 195 deletions(-) diff --git a/tools/nss/libvirt_nss_macs.c b/tools/nss/libvirt_nss_macs.c index f45d149793..dbc0790945 100644 --- a/tools/nss/libvirt_nss_macs.c +++ b/tools/nss/libvirt_nss_macs.c @@ -25,179 +25,78 @@ #include #include =20 -#include -#include +#include =20 #include "libvirt_nss_macs.h" #include "libvirt_nss.h" =20 -enum { - FIND_MACS_STATE_START, - FIND_MACS_STATE_LIST, - FIND_MACS_STATE_ENTRY, - FIND_MACS_STATE_ENTRY_MACS, -}; - -typedef struct { - const char *name; - char ***macs; - size_t *nmacs; - int state; - - char *key; - struct { - char *name; - char **macs; - size_t nmacs; - } entry; -} findMACsParser; - =20 static int -findMACsParserString(void *ctx, - const unsigned char *stringVal, - size_t stringLen) +findMACsFromJSON(json_object *jobj, + const char *name, + char ***macs, + size_t *nmacs) { - findMACsParser *parser =3D ctx; - - DEBUG("Parse string state=3D%d '%.*s' (map key '%s')", - parser->state, (int)stringLen, (const char *)stringVal, - NULLSTR(parser->key)); - if (!parser->key) - return 0; - - if (parser->state =3D=3D FIND_MACS_STATE_ENTRY) { - if (strcmp(parser->key, "domain")) - return 1; - - free(parser->entry.name); - if (!(parser->entry.name =3D strndup((char *)stringVal, stringLen)= )) - return 0; - } else if (parser->state =3D=3D FIND_MACS_STATE_ENTRY_MACS) { - char **macs; - if (strcmp(parser->key, "macs")) - return 1; + size_t i, j; + int len; =20 - if (!(macs =3D realloc(parser->entry.macs, - sizeof(char *) * (parser->entry.nmacs + 1)))) - return 0; - - parser->entry.macs =3D macs; - if (!(macs[parser->entry.nmacs++] =3D strndup((char *)stringVal, s= tringLen))) - return 0; - } else { - return 0; + if (!json_object_is_type(jobj, json_type_array)) { + ERROR("parsed JSON does not contain the leases array"); + return -1; } - return 1; -} - - -static int -findMACsParserMapKey(void *ctx, - const unsigned char *stringVal, - size_t stringLen) -{ - findMACsParser *parser =3D ctx; - - DEBUG("Parse map key state=3D%d '%.*s'", - parser->state, (int)stringLen, (const char *)stringVal); - - free(parser->key); - if (!(parser->key =3D strndup((char *)stringVal, stringLen))) - return 0; - - return 1; -} - - -static int -findMACsParserStartMap(void *ctx) -{ - findMACsParser *parser =3D ctx; =20 - DEBUG("Parse start map state=3D%d", parser->state); + len =3D json_object_array_length(jobj); + DEBUG("Found an array of length: %zu", len); + for (i =3D 0; i < len; i++) { + json_object *entry =3D NULL; + json_object *domain =3D NULL; + const char *domainName; + char **tmpMacs =3D NULL; + size_t newmacs =3D 0; + json_object *macsArray =3D NULL; =20 - if (parser->state !=3D FIND_MACS_STATE_LIST) - return 0; + entry =3D json_object_array_get_idx(jobj, i); + if (!entry) + return -1; =20 - free(parser->key); - parser->key =3D NULL; - parser->state =3D FIND_MACS_STATE_ENTRY; + DEBUG("Processing item %zu", i); =20 - return 1; -} + domain =3D json_object_object_get(entry, "domain"); + if (!domain) + return -1; =20 + domainName =3D json_object_get_string(domain); + if (!domainName) + return -1; =20 -static int -findMACsParserEndMap(void *ctx) -{ - findMACsParser *parser =3D ctx; - size_t i; + DEBUG("Processing domain %s", domainName); =20 - DEBUG("Parse end map state=3D%d", parser->state); + if (strcasecmp(domainName, name)) + continue; =20 - if (parser->entry.name =3D=3D NULL) - return 0; + macsArray =3D json_object_object_get(entry, "macs"); + if (!macsArray) + return -1; =20 - if (parser->state !=3D FIND_MACS_STATE_ENTRY) - return 0; + newmacs =3D json_object_array_length(macsArray); + DEBUG("Found %zu MAC addresses", newmacs); =20 - if (!strcasecmp(parser->entry.name, parser->name)) { - char **macs =3D realloc(*parser->macs, - sizeof(char *) * ((*parser->nmacs) + parser-= >entry.nmacs)); - if (!macs) + tmpMacs =3D realloc(*macs, sizeof(char *) * (*nmacs + newmacs + 1)= ); + if (!tmpMacs) return 0; =20 - *parser->macs =3D macs; - for (i =3D 0; i < parser->entry.nmacs; i++) - (*parser->macs)[(*parser->nmacs)++] =3D parser->entry.macs[i]; - } else { - for (i =3D 0; i < parser->entry.nmacs; i++) - free(parser->entry.macs[i]); - } - free(parser->entry.macs); - parser->entry.macs =3D NULL; - parser->entry.nmacs =3D 0; - - parser->state =3D FIND_MACS_STATE_LIST; - - return 1; -} - - -static int -findMACsParserStartArray(void *ctx) -{ - findMACsParser *parser =3D ctx; - - DEBUG("Parse start array state=3D%d", parser->state); - - if (parser->state =3D=3D FIND_MACS_STATE_START) - parser->state =3D FIND_MACS_STATE_LIST; - else if (parser->state =3D=3D FIND_MACS_STATE_ENTRY) - parser->state =3D FIND_MACS_STATE_ENTRY_MACS; - else - return 0; + *macs =3D tmpMacs; =20 - return 1; -} + for (j =3D 0; j < newmacs; j++) { + json_object *macobj =3D NULL; =20 + DEBUG("j: %zu", j); =20 -static int -findMACsParserEndArray(void *ctx) -{ - findMACsParser *parser =3D ctx; - - DEBUG("Parse end array state=3D%d", parser->state); - - if (parser->state =3D=3D FIND_MACS_STATE_LIST) - parser->state =3D FIND_MACS_STATE_START; - else if (parser->state =3D=3D FIND_MACS_STATE_ENTRY_MACS) - parser->state =3D FIND_MACS_STATE_ENTRY; - else - return 0; - - return 1; + macobj =3D json_object_array_get_idx(macsArray, j); + (*macs)[(*nmacs)++] =3D strdup(json_object_get_string(macobj)); + } + } + return 0; } =20 =20 @@ -209,66 +108,47 @@ findMACs(const char *file, { int fd =3D -1; int ret =3D -1; - const yajl_callbacks parserCallbacks =3D { - NULL, /* null */ - NULL, /* bool */ - NULL, /* integer */ - NULL, /* double */ - NULL, /* number */ - findMACsParserString, - findMACsParserStartMap, - findMACsParserMapKey, - findMACsParserEndMap, - findMACsParserStartArray, - findMACsParserEndArray, - }; - findMACsParser parserState =3D { - .name =3D name, - .macs =3D macs, - .nmacs =3D nmacs, - }; - yajl_handle parser =3D NULL; char line[1024]; - size_t i; + json_object *jobj =3D NULL; + json_tokener *tok =3D NULL; + enum json_tokener_error jerr =3D json_tokener_success; + int jsonflags =3D JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8; + ssize_t nreadTotal =3D 0; int rv; + size_t i; =20 if ((fd =3D open(file, O_RDONLY)) < 0) { ERROR("Cannot open %s", file); goto cleanup; } =20 - parser =3D yajl_alloc(&parserCallbacks, NULL, &parserState); - if (!parser) { - ERROR("Unable to create JSON parser"); - goto cleanup; - } + tok =3D json_tokener_new(); + json_tokener_set_flags(tok, jsonflags); =20 - while (1) { - rv =3D read(fd, line, sizeof(line)); + while (jerr !=3D json_tokener_continue) { + rv =3D read(fd, line, sizeof(line) - 1); if (rv < 0) goto cleanup; if (rv =3D=3D 0) break; + nreadTotal +=3D rv; =20 - if (yajl_parse(parser, (const unsigned char *)line, rv) !=3D - yajl_status_ok) { - unsigned char *err =3D yajl_get_error(parser, 1, - (const unsigned char*)line= , rv); - ERROR("Parse failed %s", (const char *) err); - yajl_free_error(parser, err); - goto cleanup; - } + line[rv] =3D 0; + + jobj =3D json_tokener_parse_ex(tok, line, rv); + jerr =3D json_tokener_get_error(tok); } =20 - if (yajl_complete_parse(parser) !=3D yajl_status_ok) { - ERROR("Parse failed %s", - yajl_get_error(parser, 1, NULL, 0)); + if (nreadTotal > 0 && jerr !=3D json_tokener_success) { + ERROR("Cannot parse %s: %s", file, json_tokener_error_desc(jerr)); goto cleanup; } =20 - ret =3D 0; + ret =3D findMACsFromJSON(jobj, name, macs, nmacs); =20 cleanup: + json_object_put(jobj); + json_tokener_free(tok); if (ret !=3D 0) { for (i =3D 0; i < *nmacs; i++) { char *mac =3D (*macs)[i]; @@ -278,13 +158,6 @@ findMACs(const char *file, *macs =3D NULL; *nmacs =3D 0; } - if (parser) - yajl_free(parser); - for (i =3D 0; i < parserState.entry.nmacs; i++) - free(parserState.entry.macs[i]); - free(parserState.entry.macs); - free(parserState.entry.name); - free(parserState.key); if (fd !=3D -1) close(fd); return ret; --=20 2.45.2