libfdisk: do not use va_list in the Ask API

# fdisk /dev/sda
  Welcome to fdisk (util-linux 2.23).

  [...]

  Command (m for help): a
  Segmentation fault (core dumped)

It's too fragile, the va_list implementation is architecture specific
and it seems we need such thing in libfdisk at all.

Reported-by: "Gabor Z. Papp" <gzp@papp.hu>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2013-05-09 13:06:02 +02:00
parent a21aa92fd4
commit 4fb18cde32
4 changed files with 13 additions and 41 deletions

View File

@ -167,7 +167,6 @@ static int ask_offset(struct fdisk_context *cxt,
int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
void *data __attribute__((__unused__)))
{
va_list ap;
int rc = 0;
char buf[BUFSIZ];
@ -180,23 +179,17 @@ int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
case FDISK_ASKTYPE_OFFSET:
return ask_offset(cxt, ask, buf, sizeof(buf));
case FDISK_ASKTYPE_INFO:
fdisk_ask_print_get_va(ask, ap);
vfprintf(stdout, fdisk_ask_print_get_mesg(ask), ap);
fputs(fdisk_ask_print_get_mesg(ask), stdout);
fputc('\n', stdout);
va_end(ap);
break;
case FDISK_ASKTYPE_WARNX:
fdisk_ask_print_get_va(ask, ap);
vfprintf(stderr, fdisk_ask_print_get_mesg(ask), ap);
fputs(fdisk_ask_print_get_mesg(ask), stderr);
fputc('\n', stderr);
va_end(ap);
break;
case FDISK_ASKTYPE_WARN:
fdisk_ask_print_get_va(ask, ap);
vfprintf(stderr, fdisk_ask_print_get_mesg(ask), ap);
fputs(fdisk_ask_print_get_mesg(ask), stderr);
errno = fdisk_ask_print_get_errno(ask);
fprintf(stderr, ": %m\n");
va_end(ap);
break;
case FDISK_ASKTYPE_YESNO:
fputc('\n', stdout);

View File

@ -18,11 +18,6 @@ void fdisk_reset_ask(struct fdisk_ask *ask)
case FDISK_ASKTYPE_NUMBER:
free(ask->data.num.range);
break;
case FDISK_ASKTYPE_WARNX:
case FDISK_ASKTYPE_WARN:
if (ask->data.print.has_va)
va_end(ask->data.print.va);
break;
default:
break;
}
@ -452,44 +447,32 @@ int fdisk_ask_print_set_mesg(struct fdisk_ask *ask, const char *mesg)
return 0;
}
/* caller has to call va_end(ap) */
int fdisk_ask_print_get_va(struct fdisk_ask *ask, va_list ap)
{
assert(ask);
assert(is_print_ask(ask));
va_copy(ap, ask->data.print.va);
return 0;
}
/* note that fdisk_free_ask() calls va_end() to free the private va list. */
int fdisk_ask_print_set_va(struct fdisk_ask *ask, va_list ap)
{
assert(ask);
va_copy(ask->data.print.va, ap);
ask->data.print.has_va = 1;
return 0;
}
static int do_vprint(struct fdisk_context *cxt, int errnum, int type,
const char *fmt, va_list va)
{
struct fdisk_ask *ask;
int rc;
char *mesg;
assert(cxt);
ask = fdisk_new_ask();
if (!ask)
if (vasprintf(&mesg, fmt, va) < 0)
return -ENOMEM;
ask = fdisk_new_ask();
if (!ask) {
free(mesg);
return -ENOMEM;
}
fdisk_ask_set_type(ask, type);
fdisk_ask_print_set_mesg(ask, fmt);
fdisk_ask_print_set_va(ask, va);
fdisk_ask_print_set_mesg(ask, mesg);
if (errnum >= 0)
fdisk_ask_print_set_errno(ask, errnum);
rc = fdisk_do_ask(cxt, ask);
fdisk_free_ask(ask);
free(mesg);
return rc;
}

View File

@ -231,8 +231,6 @@ struct fdisk_ask {
/* FDISK_ASKTYPE_{WARN,WARNX,..} */
struct ask_print {
const char *mesg;
va_list va;
unsigned int has_va:1;
int errnum; /* errno */
} print;
/* FDISK_ASKTYPE_YESNO */

View File

@ -182,8 +182,6 @@ extern int fdisk_ask_print_get_errno(struct fdisk_ask *ask);
extern int fdisk_ask_print_set_errno(struct fdisk_ask *ask, int errnum);
extern const char *fdisk_ask_print_get_mesg(struct fdisk_ask *ask);
extern int fdisk_ask_print_set_mesg(struct fdisk_ask *ask, const char *mesg);
extern int fdisk_ask_print_get_va(struct fdisk_ask *ask, va_list ap);
extern int fdisk_ask_print_set_va(struct fdisk_ask *ask, va_list ap);
#ifdef __cplusplus
}