mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	pack.c: cast from double to float can be undefined
Generally speaking, a value of double is not always representable when demoted to a float. ISO C defines what to do when such conversion loses precision, but leaves it undefined when the value is completely out of range. (cf: ISO/IEC 9899:1990 section 6.2.1.4). Because ruby do not have half-precision floating-point types this is not a frequent headache but for pack / unpack, there are specifiers that has something to do with C float types. We have to explicitly care these situations. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65768 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									3c7852f801
								
							
						
					
					
						commit
						ffd9a7ea27
					
				
					 1 changed files with 24 additions and 3 deletions
				
			
		
							
								
								
									
										27
									
								
								pack.c
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								pack.c
									
										
									
									
									
								
							|  | @ -14,6 +14,7 @@ | |||
| #include <sys/types.h> | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| #include <float.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * It is intentional that the condition for natstr is HAVE_TRUE_LONG_LONG | ||||
|  | @ -148,6 +149,26 @@ unknown_directive(const char *mode, char type, VALUE fmt) | |||
|                mode, unknown, fmt); | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| VALUE_to_float(VALUE obj) | ||||
| { | ||||
|     VALUE v = rb_to_float(obj); | ||||
|     double d = RFLOAT_VALUE(v); | ||||
| 
 | ||||
|     if (isnan(d)) { | ||||
|         return NAN; | ||||
|     } | ||||
|     else if (d < -FLT_MAX) { | ||||
|         return -INFINITY; | ||||
|     } | ||||
|     else if (d <= FLT_MAX) { | ||||
|         return d; | ||||
|     } | ||||
|     else { | ||||
|         return INFINITY; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  call-seq: | ||||
|  *     arr.pack( aTemplateString ) -> aBinaryString | ||||
|  | @ -663,7 +684,7 @@ pack_pack(int argc, VALUE *argv, VALUE ary) | |||
| 		float f; | ||||
| 
 | ||||
| 		from = NEXTFROM; | ||||
| 		f = (float)RFLOAT_VALUE(rb_to_float(from)); | ||||
|                 f = VALUE_to_float(from); | ||||
| 		rb_str_buf_cat(res, (char*)&f, sizeof(float)); | ||||
| 	    } | ||||
| 	    break; | ||||
|  | @ -673,7 +694,7 @@ pack_pack(int argc, VALUE *argv, VALUE ary) | |||
| 		FLOAT_CONVWITH(tmp); | ||||
| 
 | ||||
| 		from = NEXTFROM; | ||||
| 		tmp.f = (float)RFLOAT_VALUE(rb_to_float(from)); | ||||
|                 tmp.f = VALUE_to_float(from); | ||||
| 		HTOVF(tmp); | ||||
| 		rb_str_buf_cat(res, tmp.buf, sizeof(float)); | ||||
| 	    } | ||||
|  | @ -704,7 +725,7 @@ pack_pack(int argc, VALUE *argv, VALUE ary) | |||
| 	    while (len-- > 0) { | ||||
| 		FLOAT_CONVWITH(tmp); | ||||
| 		from = NEXTFROM; | ||||
| 		tmp.f = (float)RFLOAT_VALUE(rb_to_float(from)); | ||||
|                 tmp.f = VALUE_to_float(from); | ||||
| 		HTONF(tmp); | ||||
| 		rb_str_buf_cat(res, tmp.buf, sizeof(float)); | ||||
| 	    } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 shyouhei
						shyouhei