~ubuntu-branches/ubuntu/trusty/libjpeg-turbo/trusty-proposed

« back to all changes in this revision

Viewing changes to simd/jsimd_arm.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose, Tom Gall, Matthias Klose
  • Date: 2012-09-20 00:18:15 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20120920001815-eijk7v63d1nv0vbo
Tags: 1.2.1-0ubuntu1
[ Tom Gall ]
* Update to stable 1.2.1. LP: #1012861.
  * Addresses CVE-2012-2806. LP: #1025537.
    A Heap-based buffer overflow was found in the way libjpeg-turbo
    decompressed certain corrupt JPEG images in which the component count
    was erroneously set to a large value. An attacker could create a
    specially-crafted JPEG image that, when opened, could cause an
    application using libpng to crash or, possibly, execute arbitrary code
    with the privileges of the user running the application.
  * Cosmetic fixes to argument lists
  * Added flags to the TurboJPEG API that allow the caller to force
    the use of either the fast or the accurate DCT/IDCT algorithms
    in the underlying codec.
  * More recent versions of autoconf add -traditional-cpp to the CPP
    flags, which causes jsimdcfg.inc.h to not preprocess correctly
    unless we expand all of the instances of the #definev macro.
  * Fixed regression caused by a bug in the 32-bit strict memory access
    code in jdmrgss2.asm (contributed by Chromium to stop valgrind from
    whining whenever the output buffer size was not evenly divisible by
    16 bytes.)  On Linux/x86, this regression generated incorrect
    pixels on the right-hand side of images whose rows were not 16-byte
    aligned, whenever fancy upsampling was used.  This patch also
    enables the strict memory access code on all platforms, not just
    Linux (it does no harm on other platforms) and removes a couple of
    pcmpeqb instructions that were rendered unnecessary by r835.
  * Accelerated 4:2:2 upsampling routine for ARM (improves
    performance ~20-30% when decompressing 4:2:2 JPEGs using
    fancy upsampling)
  * Eliminate the use of the MASKMOVDQU instruction, to speed
    up decompression performance by 10x on AMD Bobcat embedded
    processors (and ~5% on AMD desktop processors.)
  * add tjbench to libjpeg-turbo-test packages
  * Guard against num_components being a ridiculous
    value due to a corrupt header
  * Preserve all 128 bits of xmm6 and xmm7

[ Matthias Klose ]
* Prepare the package for quantal, basing on the 1.2.1 release tarball.
* d/patches/branch-updates.diff: Update to 20120919 of the 1.2.x branch,
  but don't bump the version to 1.2.2.
* d/patches/guard-inline-define: Remove, integrated upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 * Based on the stubs from 'jsimd_none.c'
16
16
 */
17
17
 
18
 
#include <stdio.h>
19
 
#include <link.h>
20
 
#include <elf.h>
21
 
#include <asm/hwcap.h>
22
 
#include <string.h>
23
 
#include <ctype.h>
24
 
 
25
18
#define JPEG_INTERNALS
26
19
#include "../jinclude.h"
27
20
#include "../jpeglib.h"
30
23
#include "../jsimddct.h"
31
24
#include "jsimd.h"
32
25
 
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
#include <ctype.h>
 
29
 
33
30
static unsigned int simd_support = ~0;
34
31
 
35
 
extern volatile ElfW(auxv_t) *auxv;
 
32
#if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
 
33
 
 
34
#define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT (1024 * 1024)
 
35
 
 
36
LOCAL(int)
 
37
check_feature (char *buffer, char *feature)
 
38
{
 
39
  char *p;
 
40
  if (*feature == 0)
 
41
    return 0;
 
42
  if (strncmp(buffer, "Features", 8) != 0)
 
43
    return 0;
 
44
  buffer += 8;
 
45
  while (isspace(*buffer))
 
46
    buffer++;
 
47
 
 
48
  /* Check if 'feature' is present in the buffer as a separate word */
 
49
  while ((p = strstr(buffer, feature))) {
 
50
    if (p > buffer && !isspace(*(p - 1))) {
 
51
      buffer++;
 
52
      continue;
 
53
    }
 
54
    p += strlen(feature);
 
55
    if (*p != 0 && !isspace(*p)) {
 
56
      buffer++;
 
57
      continue;
 
58
    }
 
59
    return 1;
 
60
  }
 
61
  return 0;
 
62
}
 
63
 
 
64
LOCAL(int)
 
65
parse_proc_cpuinfo (int bufsize)
 
66
{
 
67
  char *buffer = (char *)malloc(bufsize);
 
68
  FILE *fd;
 
69
  simd_support = 0;
 
70
 
 
71
  if (!buffer)
 
72
    return 0;
 
73
 
 
74
  fd = fopen("/proc/cpuinfo", "r");
 
75
  if (fd) {
 
76
    while (fgets(buffer, bufsize, fd)) {
 
77
      if (!strchr(buffer, '\n') && !feof(fd)) {
 
78
        /* "impossible" happened - insufficient size of the buffer! */
 
79
        fclose(fd);
 
80
        free(buffer);
 
81
        return 0;
 
82
      }
 
83
      if (check_feature(buffer, "neon"))
 
84
        simd_support |= JSIMD_ARM_NEON;
 
85
    }
 
86
    fclose(fd);
 
87
  }
 
88
  free(buffer);
 
89
  return 1;
 
90
}
 
91
 
 
92
#endif
36
93
 
37
94
/*
38
95
 * Check what SIMD accelerations are supported.
39
 
 * this is called once and ONLY once from libjpeg_general_init
 
96
 *
 
97
 * FIXME: This code is racy under a multi-threaded environment.
40
98
 */
41
 
GLOBAL(void)
 
99
LOCAL(void)
42
100
init_simd (void)
43
101
{
44
 
  char *env=NULL;
45
 
  ElfW(auxv_t) *tauxv=(ElfW(auxv_t) *)auxv;
 
102
  char *env = NULL;
 
103
#if !defined(__ARM_NEON__) && defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
 
104
  int bufsize = 1024; /* an initial guess for the line buffer size limit */
 
105
#endif
46
106
 
47
 
  if (simd_support != ~0)
 
107
  if (simd_support != ~0U)
48
108
    return;
 
109
 
49
110
  simd_support = 0;
50
111
 
51
 
  while (tauxv && tauxv->a_type != AT_HWCAP)
52
 
    tauxv++;
 
112
#if defined(__ARM_NEON__)
 
113
  simd_support |= JSIMD_ARM_NEON;
 
114
#elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
 
115
  /* We still have a chance to use NEON regardless of globally used
 
116
   * -mcpu/-mfpu options passed to gcc by performing runtime detection via
 
117
   * /proc/cpuinfo parsing on linux/android */
 
118
  while (!parse_proc_cpuinfo(bufsize)) {
 
119
    bufsize *= 2;
 
120
    if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT)
 
121
      break;
 
122
  }
 
123
#endif
53
124
 
54
 
  if( tauxv && tauxv->a_un.a_val & HWCAP_NEON ) 
55
 
    simd_support |= JSIMD_ARM_NEON;
56
 
  
57
125
  /* Force different settings through environment variables */
58
126
  env = getenv("JSIMD_FORCE_ARM_NEON");
59
127
  if ((env != NULL) && (strcmp(env, "1") == 0))
66
134
GLOBAL(int)
67
135
jsimd_can_rgb_ycc (void)
68
136
{
 
137
  init_simd();
 
138
 
69
139
  /* The code is optimised for these values only */
70
140
  if (BITS_IN_JSAMPLE != 8)
71
141
    return 0;
83
153
GLOBAL(int)
84
154
jsimd_can_rgb_gray (void)
85
155
{
 
156
  init_simd();
 
157
 
86
158
  return 0;
87
159
}
88
160
 
89
161
GLOBAL(int)
90
162
jsimd_can_ycc_rgb (void)
91
163
{
 
164
  init_simd();
 
165
 
92
166
  /* The code is optimised for these values only */
93
167
  if (BITS_IN_JSAMPLE != 8)
94
168
    return 0;
194
268
GLOBAL(int)
195
269
jsimd_can_h2v2_downsample (void)
196
270
{
 
271
  init_simd();
 
272
 
197
273
  return 0;
198
274
}
199
275
 
200
276
GLOBAL(int)
201
277
jsimd_can_h2v1_downsample (void)
202
278
{
 
279
  init_simd();
 
280
 
203
281
  return 0;
204
282
}
205
283
 
218
296
GLOBAL(int)
219
297
jsimd_can_h2v2_upsample (void)
220
298
{
 
299
  init_simd();
 
300
 
221
301
  return 0;
222
302
}
223
303
 
224
304
GLOBAL(int)
225
305
jsimd_can_h2v1_upsample (void)
226
306
{
 
307
  init_simd();
 
308
 
227
309
  return 0;
228
310
}
229
311
 
246
328
GLOBAL(int)
247
329
jsimd_can_h2v2_fancy_upsample (void)
248
330
{
 
331
  init_simd();
 
332
 
249
333
  return 0;
250
334
}
251
335
 
252
336
GLOBAL(int)
253
337
jsimd_can_h2v1_fancy_upsample (void)
254
338
{
 
339
  init_simd();
 
340
 
 
341
  /* The code is optimised for these values only */
 
342
  if (BITS_IN_JSAMPLE != 8)
 
343
    return 0;
 
344
  if (sizeof(JDIMENSION) != 4)
 
345
    return 0;
 
346
 
 
347
  if (simd_support & JSIMD_ARM_NEON)
 
348
    return 1;
 
349
 
255
350
  return 0;
256
351
}
257
352
 
269
364
                           JSAMPARRAY input_data,
270
365
                           JSAMPARRAY * output_data_ptr)
271
366
{
 
367
  if (simd_support & JSIMD_ARM_NEON)
 
368
    jsimd_h2v1_fancy_upsample_neon(cinfo->max_v_samp_factor,
 
369
        compptr->downsampled_width, input_data, output_data_ptr);
272
370
}
273
371
 
274
372
GLOBAL(int)
275
373
jsimd_can_h2v2_merged_upsample (void)
276
374
{
 
375
  init_simd();
 
376
 
277
377
  return 0;
278
378
}
279
379
 
280
380
GLOBAL(int)
281
381
jsimd_can_h2v1_merged_upsample (void)
282
382
{
 
383
  init_simd();
 
384
 
283
385
  return 0;
284
386
}
285
387
 
302
404
GLOBAL(int)
303
405
jsimd_can_convsamp (void)
304
406
{
 
407
  init_simd();
 
408
 
305
409
  /* The code is optimised for these values only */
306
410
  if (DCTSIZE != 8)
307
411
    return 0;
321
425
GLOBAL(int)
322
426
jsimd_can_convsamp_float (void)
323
427
{
 
428
  init_simd();
 
429
 
324
430
  return 0;
325
431
}
326
432
 
341
447
GLOBAL(int)
342
448
jsimd_can_fdct_islow (void)
343
449
{
 
450
  init_simd();
 
451
 
344
452
  return 0;
345
453
}
346
454
 
347
455
GLOBAL(int)
348
456
jsimd_can_fdct_ifast (void)
349
457
{
 
458
  init_simd();
 
459
 
350
460
  /* The code is optimised for these values only */
351
461
  if (DCTSIZE != 8)
352
462
    return 0;
362
472
GLOBAL(int)
363
473
jsimd_can_fdct_float (void)
364
474
{
 
475
  init_simd();
 
476
 
365
477
  return 0;
366
478
}
367
479
 
385
497
GLOBAL(int)
386
498
jsimd_can_quantize (void)
387
499
{
 
500
  init_simd();
 
501
 
388
502
  /* The code is optimised for these values only */
389
503
  if (DCTSIZE != 8)
390
504
    return 0;
402
516
GLOBAL(int)
403
517
jsimd_can_quantize_float (void)
404
518
{
 
519
  init_simd();
 
520
 
405
521
  return 0;
406
522
}
407
523
 
422
538
GLOBAL(int)
423
539
jsimd_can_idct_2x2 (void)
424
540
{
 
541
  init_simd();
 
542
 
425
543
  /* The code is optimised for these values only */
426
544
  if (DCTSIZE != 8)
427
545
    return 0;
443
561
GLOBAL(int)
444
562
jsimd_can_idct_4x4 (void)
445
563
{
 
564
  init_simd();
 
565
 
446
566
  /* The code is optimised for these values only */
447
567
  if (DCTSIZE != 8)
448
568
    return 0;
482
602
GLOBAL(int)
483
603
jsimd_can_idct_islow (void)
484
604
{
 
605
  init_simd();
 
606
 
485
607
  /* The code is optimised for these values only */
486
608
  if (DCTSIZE != 8)
487
609
    return 0;
503
625
GLOBAL(int)
504
626
jsimd_can_idct_ifast (void)
505
627
{
 
628
  init_simd();
 
629
 
506
630
  /* The code is optimised for these values only */
507
631
  if (DCTSIZE != 8)
508
632
    return 0;
526
650
GLOBAL(int)
527
651
jsimd_can_idct_float (void)
528
652
{
 
653
  init_simd();
 
654
 
529
655
  return 0;
530
656
}
531
657