代码拉取完成,页面将自动刷新
From d58e447819e96d84560b16d7632bb7bdf88cc412 Mon Sep 17 00:00:00 2001
From: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
Date: Tue, 16 Jun 2015 10:43:21 -0700
Subject: [PATCH 04/55] grubby: properly handle mixed ' and " and nested quotes
The SLES12 grub2.cfg file on ppc64le by default contains a line like:
submenu "Bootable snapshot #$snapshot_num" {
menuentry "If OK, run 'snapper rollback $snapshot_num' reboot." { true; }
}
On any grubby (tested with 8.40) invocation that updates the config
file, the combination of nested quotes and mixed quotes leads to a
generated file content like:
submenu "Bootable snapshot #$snapshot_num" {
menuentry 'If OK, run snapper rollback $snapshot_num' rollback $snapshot_num' and reboot." { true; }
}
which includes both a change from " to ', but also improperly quoted
strings and trailing characters relative to the string. This actually
leads to a failure to boot from the disk by default when using grubby
(e.g., Autotest) on SLES12 ppc64le. Whether SLES12 should be adding an
entry like this by default or not is probably open to debate, but grubby
should be able to hand this input file.
To fix the issue, three changes were necessary:
1) grub2ExtractTitle needs to check that if the second element starts
with a quote, that the matching element found ends with the same
quote-type (' vs. ")
2) lineWrite needs to output the right kind of quote based upon if the
string to be outputted itself contains quotes. This is not currently
possible in the code, because quotes are stripped out normally by
readConfig, but with the change in 3), that only happens now for the
quotes that actually delineate a string.
3) readConfig needs to check that when it is extracting titles and
determining extras, it uses matching quotes.
With these changes, a simple grubby --set-default=SLES12 (for example),
now produces:
submenu "Bootable snapshot #$snapshot_num" {
menuentry "If OK, run 'snapper rollback $snapshot_num' and reboot." { true; }
}
as expected.
Signed-off-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
---
grubby.c | 42 +++++++++++++++++++++++++++++++++---------
1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/grubby.c b/grubby.c
index 53fe9250e27..440c6277935 100644
--- a/grubby.c
+++ b/grubby.c
@@ -451,6 +451,8 @@ char *grub2ExtractTitle(struct singleLine * line) {
* whose last character is also quote (assuming it's the closing one) */
int resultMaxSize;
char * result;
+ /* need to ensure that ' does not match " as we search */
+ char quote_char = *current;
resultMaxSize = sizeOfSingleLine(line);
result = malloc(resultMaxSize);
@@ -464,7 +466,7 @@ char *grub2ExtractTitle(struct singleLine * line) {
current_indent_len = strlen(current_indent);
strncat(result, current_indent, current_indent_len);
- if (!isquote(current[current_len-1])) {
+ if (current[current_len-1] != quote_char) {
strncat(result, current, current_len);
} else {
strncat(result, current, current_len - 1);
@@ -928,10 +930,23 @@ static int lineWrite(FILE * out, struct singleLine * line,
/* Need to handle this, because we strip the quotes from
* menuentry when read it. */
if (line->type == LT_MENUENTRY && i == 1) {
- if(!isquote(*line->elements[i].item))
- fprintf(out, "\'%s\'", line->elements[i].item);
- else
+ if(!isquote(*line->elements[i].item)) {
+ int substring = 0;
+ /* If the line contains nested quotes, we did not strip
+ * the "interna" quotes and we must use the right quotes
+ * again when writing the updated file. */
+ for (int j = i; j < line->numElements; j++) {
+ if (strchr(line->elements[i].item, '\'') != NULL) {
+ substring = 1;
+ fprintf(out, "\"%s\"", line->elements[i].item);
+ break;
+ }
+ }
+ if (!substring)
+ fprintf(out, "\'%s\'", line->elements[i].item);
+ } else {
fprintf(out, "%s", line->elements[i].item);
+ }
fprintf(out, "%s", line->elements[i].indent);
continue;
@@ -1267,6 +1282,8 @@ static struct grubConfig * readConfig(const char * inName,
len = 0;
char *extras;
char *title;
+ /* initially unseen value */
+ char quote_char = '\0';
for (int i = 1; i < line->numElements; i++) {
len += strlen(line->elements[i].item);
@@ -1283,13 +1300,16 @@ static struct grubConfig * readConfig(const char * inName,
for (int i = 0; i < line->numElements; i++) {
if (!strcmp(line->elements[i].item, "menuentry"))
continue;
- if (isquote(*line->elements[i].item))
+ if (isquote(*line->elements[i].item) && quote_char == '\0') {
+ /* ensure we properly pair off quotes */
+ quote_char = *line->elements[i].item;
title = line->elements[i].item + 1;
- else
+ } else {
title = line->elements[i].item;
+ }
len = strlen(title);
- if (isquote(title[len-1])) {
+ if (title[len-1] == quote_char) {
strncat(buf, title,len-1);
break;
} else {
@@ -1300,6 +1320,7 @@ static struct grubConfig * readConfig(const char * inName,
/* get extras */
int count = 0;
+ quote_char = '\0';
for (int i = 0; i < line->numElements; i++) {
if (count >= 2) {
strcat(extras, line->elements[i].item);
@@ -1310,12 +1331,15 @@ static struct grubConfig * readConfig(const char * inName,
continue;
/* count ' or ", there should be two in menuentry line. */
- if (isquote(*line->elements[i].item))
+ if (isquote(*line->elements[i].item) && quote_char == '\0') {
+ /* ensure we properly pair off quotes */
+ quote_char = *line->elements[i].item;
count++;
+ }
len = strlen(line->elements[i].item);
- if (isquote(line->elements[i].item[len -1]))
+ if (line->elements[i].item[len -1] == quote_char)
count++;
/* ok, we get the final ' or ", others are extras. */
--
2.17.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。