XkbCopyKeymap: be more careful with levels, allocate compat/geom

Take various extra precautions with copying levels across (thanks Chris
Lee for a gdb session), including allocating when we don't already have a
coherent map.
Only free type components if they're present.
Allocate geometry and compat components if we don't already have them in
the dest map.
This commit is contained in:
Daniel Stone 2006-11-02 00:45:23 +02:00 committed by Daniel Stone
parent d7d931abe0
commit d9a5e3e964

View File

@ -1082,28 +1082,39 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
stype = src->map->types; stype = src->map->types;
dtype = dst->map->types; dtype = dst->map->types;
for (i = 0; i < src->map->num_types; i++, dtype++, stype++) { for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
if (stype->num_levels != dtype->num_levels) { if (stype->num_levels) {
if (dtype->level_names) if (stype->num_levels != dtype->num_levels &&
dtype->num_levels && dtype->level_names) {
tmp = xrealloc(dtype->level_names, tmp = xrealloc(dtype->level_names,
stype->num_levels * sizeof(Atom)); stype->num_levels * sizeof(Atom));
else if (!tmp)
continue;
dtype->level_names = tmp;
}
else if (!dtype->num_levels || !dtype->level_names) {
tmp = xalloc(stype->num_levels * sizeof(Atom)); tmp = xalloc(stype->num_levels * sizeof(Atom));
if (!tmp) if (!tmp)
continue; /* don't return FALSE here, try to whack continue;
all the pointers we can, so we don't
double-free when going down. */
dtype->level_names = tmp; dtype->level_names = tmp;
dtype->num_levels = stype->num_levels;
} }
dtype->num_levels = stype->num_levels;
memcpy(dtype->level_names, stype->level_names, memcpy(dtype->level_names, stype->level_names,
stype->num_levels * sizeof(Atom)); stype->num_levels * sizeof(Atom));
}
else {
if (dtype->num_levels && dtype->level_names)
xfree(dtype->level_names);
dtype->num_levels = 0;
dtype->level_names = NULL;
}
dtype->name = stype->name; dtype->name = stype->name;
memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec)); memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
if (stype->map_count) {
if (stype->map) { if (stype->map) {
if (dtype->map) { if (stype->map_count != dtype->map_count &&
if (stype->map_count != dtype->map_count) { dtype->map_count && dtype->map) {
tmp = xrealloc(dtype->map, tmp = xrealloc(dtype->map,
stype->map_count * stype->map_count *
sizeof(XkbKTMapEntryRec)); sizeof(XkbKTMapEntryRec));
@ -1111,8 +1122,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
return FALSE; return FALSE;
dtype->map = tmp; dtype->map = tmp;
} }
} else if (!dtype->map_count || !dtype->map) {
else {
tmp = xalloc(stype->map_count * tmp = xalloc(stype->map_count *
sizeof(XkbKTMapEntryRec)); sizeof(XkbKTMapEntryRec));
if (!tmp) if (!tmp)
@ -1120,14 +1130,13 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
dtype->map = tmp; dtype->map = tmp;
} }
dtype->map_count = stype->map_count; memcpy(dtype->map, stype->map,
memcpy(dtype->map, stype->map, stype->map_count * stype->map_count * sizeof(XkbKTMapEntryRec));
sizeof(XkbKTMapEntryRec));
} }
if (stype->preserve) { if (stype->preserve) {
if (dtype->preserve) { if (stype->map_count != dtype->map_count &&
if (stype->map_count != dtype->map_count) { dtype->map_count && dtype->preserve) {
tmp = xrealloc(dtype->preserve, tmp = xrealloc(dtype->preserve,
stype->map_count * stype->map_count *
sizeof(XkbModsRec)); sizeof(XkbModsRec));
@ -1135,9 +1144,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
return FALSE; return FALSE;
dtype->preserve = tmp; dtype->preserve = tmp;
} }
} else if (!dtype->preserve || !dtype->map_count) {
else { tmp = xalloc(stype->map_count *
tmp = xalloc(stype->map_count * sizeof(XkbModsRec)); sizeof(XkbModsRec));
if (!tmp) if (!tmp)
return FALSE; return FALSE;
dtype->preserve = tmp; dtype->preserve = tmp;
@ -1146,11 +1155,19 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
memcpy(dtype->preserve, stype->preserve, memcpy(dtype->preserve, stype->preserve,
stype->map_count * sizeof(XkbModsRec)); stype->map_count * sizeof(XkbModsRec));
} }
else {
if (dtype->preserve) { dtype->map_count = stype->map_count;
xfree(dtype->preserve);
dtype->preserve = NULL;
} }
else {
if (dtype->map_count) {
if (dtype->map)
xfree(dtype->map);
if (dtype->preserve)
xfree(dtype->preserve);
dtype->map_count = 0;
}
dtype->map = NULL;
dtype->preserve = NULL;
} }
} }
} }
@ -1160,9 +1177,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
i++, dtype++) { i++, dtype++) {
if (dtype->level_names) if (dtype->level_names)
xfree(dtype->level_names); xfree(dtype->level_names);
if (dtype->map) if (dtype->map && dtype->map_count)
xfree(dtype->map); xfree(dtype->map);
if (dtype->preserve) if (dtype->preserve && dtype->preserve)
xfree(dtype->preserve); xfree(dtype->preserve);
} }
xfree(dst->map->types); xfree(dst->map->types);
@ -1451,6 +1468,12 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
/* compat */ /* compat */
if (src->compat) { if (src->compat) {
if (!dst->compat) {
dst->compat = xcalloc(1, sizeof(XkbCompatMapRec));
if (!dst->compat)
return FALSE;
}
if (src->compat->sym_interpret) { if (src->compat->sym_interpret) {
if (src->compat->size_si != dst->compat->size_si) { if (src->compat->size_si != dst->compat->size_si) {
if (dst->compat->sym_interpret) if (dst->compat->sym_interpret)
@ -1486,6 +1509,12 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
/* geometry */ /* geometry */
if (src->geom) { if (src->geom) {
if (!dst->geom) {
dst->geom = xcalloc(sizeof(XkbGeometryRec), 1);
if (!dst->geom)
return FALSE;
}
/* properties */ /* properties */
if (src->geom->num_properties) { if (src->geom->num_properties) {
if (src->geom->num_properties != dst->geom->sz_properties) { if (src->geom->num_properties != dst->geom->sz_properties) {