summaryrefslogtreecommitdiff
path: root/common.c
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2017-04-17 13:01:04 +0100
committerDaniel Stone <daniels@collabora.com>2017-05-02 19:07:42 +0100
commitc84b17c5761059f7c8490bf6a4e0a2beec74f9b1 (patch)
tree2d4181e079cd204b01c67999f179ea3b331f3daf /common.c
parentd8bb13790524f597fa1e07b198619a260aec6740 (diff)
downloadkmscube-c84b17c5761059f7c8490bf6a4e0a2beec74f9b1.tar.gz
common: Check for extensions before resolving symbols
eglGetProcAddress is allowed to return any old garbage for symbols it doesn't know about. To avoid any mishaps, check for the appropriate extension presence (split into EGL client extension, EGL display extension, and GL extension, checks) before we look up any symbols through it. The walk through the extension list is taken from libepoxy. Signed-off-by: Daniel Stone <daniels@collabora.com> Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Diffstat (limited to 'common.c')
-rw-r--r--common.c63
1 files changed, 51 insertions, 12 deletions
diff --git a/common.c b/common.c
index 610ff87..8f29b93 100644
--- a/common.c
+++ b/common.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2017 Rob Clark <rclark@redhat.com>
+ * Copyright © 2013 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,6 +24,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -78,6 +80,26 @@ const struct gbm * init_gbm(int drm_fd, int w, int h, uint64_t modifier)
return &gbm;
}
+static bool has_ext(const char *extension_list, const char *ext)
+{
+ const char *ptr = extension_list;
+ int len = strlen(ext);
+
+ if (ptr == NULL || *ptr == '\0')
+ return false;
+
+ while (true) {
+ ptr = strstr(ptr, ext);
+ if (!ptr)
+ return false;
+
+ if (ptr[len] == ' ' || ptr[len] == '\0')
+ return true;
+
+ ptr += len;
+ }
+}
+
int init_egl(struct egl *egl, const struct gbm *gbm)
{
EGLint major, minor, n;
@@ -96,19 +118,24 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
+ const char *egl_exts_client, *egl_exts_dpy, *gl_exts;
+
+#define get_proc_client(ext, name) do { \
+ if (has_ext(egl_exts_client, #ext)) \
+ egl->name = (void *)eglGetProcAddress(#name); \
+ } while (0)
+#define get_proc_dpy(ext, name) do { \
+ if (has_ext(egl_exts_dpy, #ext)) \
+ egl->name = (void *)eglGetProcAddress(#name); \
+ } while (0)
-#define get_proc(name) do { \
- egl->name = (void *)eglGetProcAddress(#name); \
+#define get_proc_gl(ext, name) do { \
+ if (has_ext(gl_exts, #ext)) \
+ egl->name = (void *)eglGetProcAddress(#name); \
} while (0)
- get_proc(eglGetPlatformDisplayEXT);
- get_proc(eglCreateImageKHR);
- get_proc(eglDestroyImageKHR);
- get_proc(glEGLImageTargetTexture2DOES);
- get_proc(eglCreateSyncKHR);
- get_proc(eglDestroySyncKHR);
- get_proc(eglWaitSyncKHR);
- get_proc(eglDupNativeFenceFDANDROID);
+ egl_exts_client = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ get_proc_client(EGL_EXT_platform_base, eglGetPlatformDisplayEXT);
if (egl->eglGetPlatformDisplayEXT) {
egl->display = egl->eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR,
@@ -122,6 +149,14 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
return -1;
}
+ egl_exts_dpy = eglQueryString(egl->display, EGL_EXTENSIONS);
+ get_proc_dpy(EGL_KHR_image_base, eglCreateImageKHR);
+ get_proc_dpy(EGL_KHR_image_base, eglDestroyImageKHR);
+ get_proc_dpy(EGL_KHR_fence_sync, eglCreateSyncKHR);
+ get_proc_dpy(EGL_KHR_fence_sync, eglDestroySyncKHR);
+ get_proc_dpy(EGL_KHR_fence_sync, eglWaitSyncKHR);
+ get_proc_dpy(EGL_ANDROID_native_fence_sync, eglDupNativeFenceFDANDROID);
+
printf("Using display %p with EGL version %d.%d\n",
egl->display, major, minor);
@@ -129,7 +164,8 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
printf("EGL information:\n");
printf(" version: \"%s\"\n", eglQueryString(egl->display, EGL_VERSION));
printf(" vendor: \"%s\"\n", eglQueryString(egl->display, EGL_VENDOR));
- printf(" extensions: \"%s\"\n", eglQueryString(egl->display, EGL_EXTENSIONS));
+ printf(" client extensions: \"%s\"\n", egl_exts_client);
+ printf(" display extensions: \"%s\"\n", egl_exts_dpy);
printf("===================================\n");
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
@@ -159,14 +195,17 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
/* connect the context to the surface */
eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context);
+ gl_exts = (char *) glGetString(GL_EXTENSIONS);
printf("OpenGL ES 2.x information:\n");
printf(" version: \"%s\"\n", glGetString(GL_VERSION));
printf(" shading language version: \"%s\"\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
printf(" vendor: \"%s\"\n", glGetString(GL_VENDOR));
printf(" renderer: \"%s\"\n", glGetString(GL_RENDERER));
- printf(" extensions: \"%s\"\n", glGetString(GL_EXTENSIONS));
+ printf(" extensions: \"%s\"\n", gl_exts);
printf("===================================\n");
+ get_proc_gl(GL_OES_EGL_image, glEGLImageTargetTexture2DOES);
+
return 0;
}